ccxt 4.5.56 → 4.5.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -9
- package/dist/ccxt.browser.min.js +10 -10
- package/dist/cjs/ccxt.js +6 -11
- package/dist/cjs/src/apex.js +1 -1
- package/dist/cjs/src/arkham.js +3 -3
- package/dist/cjs/src/ascendex.js +2 -2
- package/dist/cjs/src/aster.js +7 -4
- package/dist/cjs/src/backpack.js +4 -4
- package/dist/cjs/src/base/Exchange.js +69 -32
- package/dist/cjs/src/base/functions/io.js +25 -0
- package/dist/cjs/src/base/functions.js +1 -0
- package/dist/cjs/src/bigone.js +3 -3
- package/dist/cjs/src/binance.js +192 -194
- package/dist/cjs/src/bingx.js +3 -3
- package/dist/cjs/src/bitfinex.js +71 -58
- package/dist/cjs/src/bitget.js +2 -2
- package/dist/cjs/src/bitmart.js +13 -6
- package/dist/cjs/src/bitmex.js +1 -1
- package/dist/cjs/src/bitopro.js +1 -1
- package/dist/cjs/src/bitrue.js +2 -2
- package/dist/cjs/src/bitso.js +1 -1
- package/dist/cjs/src/bitstamp.js +2 -1
- package/dist/cjs/src/bitteam.js +1 -1
- package/dist/cjs/src/bittrade.js +0 -1
- package/dist/cjs/src/bitvavo.js +457 -34
- package/dist/cjs/src/blofin.js +26 -3
- package/dist/cjs/src/bullish.js +6 -5
- package/dist/cjs/src/bydfi.js +1 -1
- package/dist/cjs/src/cex.js +3 -3
- package/dist/cjs/src/coinbase.js +75 -65
- package/dist/cjs/src/coinbaseexchange.js +2 -2
- package/dist/cjs/src/coinbaseinternational.js +2 -1
- package/dist/cjs/src/coinex.js +74 -74
- package/dist/cjs/src/coinmetro.js +1 -1
- package/dist/cjs/src/coinsph.js +1 -1
- package/dist/cjs/src/cryptocom.js +46 -48
- package/dist/cjs/src/cryptomus.js +43 -39
- package/dist/cjs/src/deepcoin.js +3 -2
- package/dist/cjs/src/delta.js +51 -52
- package/dist/cjs/src/deribit.js +31 -33
- package/dist/cjs/src/derive.js +26 -28
- package/dist/cjs/src/digifinex.js +43 -44
- package/dist/cjs/src/exmo.js +92 -83
- package/dist/cjs/src/extended.js +3497 -0
- package/dist/cjs/src/foxbit.js +71 -75
- package/dist/cjs/src/gate.js +53 -53
- package/dist/cjs/src/gemini.js +41 -43
- package/dist/cjs/src/grvt.js +4 -4
- package/dist/cjs/src/hashkey.js +52 -54
- package/dist/cjs/src/hitbtc.js +3 -13
- package/dist/cjs/src/hollaex.js +51 -54
- package/dist/cjs/src/htx.js +75 -67
- package/dist/cjs/src/hyperliquid.js +41 -42
- package/dist/cjs/src/indodax.js +2 -2
- package/dist/cjs/src/kraken.js +57 -58
- package/dist/cjs/src/kucoin.js +3 -2
- package/dist/cjs/src/latoken.js +30 -32
- package/dist/cjs/src/lbank.js +56 -56
- package/dist/cjs/src/lighter.js +35 -37
- package/dist/cjs/src/luno.js +35 -43
- package/dist/cjs/src/mexc.js +48 -49
- package/dist/cjs/src/modetrade.js +50 -52
- package/dist/cjs/src/ndax.js +35 -37
- package/dist/cjs/src/okx.js +17 -2
- package/dist/cjs/src/onetrading.js +21 -23
- package/dist/cjs/src/phemex.js +43 -45
- package/dist/cjs/src/poloniex.js +17 -12
- package/dist/cjs/src/pro/alpaca.js +1 -1
- package/dist/cjs/src/pro/apex.js +1 -1
- package/dist/cjs/src/pro/arkham.js +1 -1
- package/dist/cjs/src/pro/backpack.js +1 -1
- package/dist/cjs/src/pro/binance.js +3 -3
- package/dist/cjs/src/pro/bitget.js +1 -1
- package/dist/cjs/src/pro/bithumb.js +1 -1
- package/dist/cjs/src/pro/bitstamp.js +1 -1
- package/dist/cjs/src/pro/blockchaincom.js +1 -1
- package/dist/cjs/src/pro/bybit.js +1 -1
- package/dist/cjs/src/pro/cex.js +1 -1
- package/dist/cjs/src/pro/coinex.js +1 -1
- package/dist/cjs/src/pro/coinone.js +1 -1
- package/dist/cjs/src/pro/cryptocom.js +3 -1
- package/dist/cjs/src/pro/dydx.js +1 -1
- package/dist/cjs/src/pro/exmo.js +1 -1
- package/dist/cjs/src/pro/extended.js +865 -0
- package/dist/cjs/src/pro/gate.js +1 -1
- package/dist/cjs/src/pro/independentreserve.js +1 -1
- package/dist/cjs/src/pro/kucoin.js +1 -1
- package/dist/cjs/src/pro/luno.js +3 -3
- package/dist/cjs/src/pro/onetrading.js +1 -1
- package/dist/cjs/src/pro/toobit.js +1 -1
- package/dist/cjs/src/pro/weex.js +1 -1
- package/dist/cjs/src/static_dependencies/starknet/utils/hash/classHash.js +7 -7
- package/dist/cjs/src/tokocrypto.js +1 -1
- package/dist/cjs/src/toobit.js +2 -2
- package/dist/cjs/src/upbit.js +3 -3
- package/dist/cjs/src/weex.js +57 -62
- package/dist/cjs/src/whitebit.js +61 -63
- package/dist/cjs/src/woo.js +65 -54
- package/dist/cjs/src/woofipro.js +53 -47
- package/dist/cjs/src/xt.js +1 -1
- package/dist/cjs/src/zebpay.js +70 -72
- package/js/ccxt.d.ts +8 -14
- package/js/ccxt.js +6 -10
- package/js/src/abstract/bitvavo.d.ts +15 -7
- package/js/src/abstract/extended.d.ts +58 -0
- package/js/src/apex.js +1 -1
- package/js/src/arkham.js +3 -3
- package/js/src/ascendex.js +2 -2
- package/js/src/aster.js +7 -4
- package/js/src/backpack.js +4 -4
- package/js/src/base/Exchange.d.ts +10 -6
- package/js/src/base/Exchange.js +69 -32
- package/js/src/base/functions/io.d.ts +7 -0
- package/js/src/base/functions/io.js +24 -0
- package/js/src/bigone.js +3 -3
- package/js/src/binance.d.ts +2 -0
- package/js/src/binance.js +196 -198
- package/js/src/bingx.js +3 -3
- package/js/src/bitfinex.d.ts +2 -0
- package/js/src/bitfinex.js +71 -58
- package/js/src/bitget.js +2 -2
- package/js/src/bitmart.js +13 -6
- package/js/src/bitmex.js +1 -1
- package/js/src/bitopro.js +1 -1
- package/js/src/bitrue.js +2 -2
- package/js/src/bitso.js +1 -1
- package/js/src/bitstamp.js +2 -1
- package/js/src/bitteam.js +1 -1
- package/js/src/bittrade.js +0 -1
- package/js/src/bitvavo.d.ts +114 -21
- package/js/src/bitvavo.js +457 -34
- package/js/src/blofin.d.ts +1 -0
- package/js/src/blofin.js +26 -3
- package/js/src/bullish.js +6 -5
- package/js/src/bydfi.js +1 -1
- package/js/src/cex.js +3 -3
- package/js/src/coinbase.d.ts +63 -56
- package/js/src/coinbase.js +75 -65
- package/js/src/coinbaseexchange.js +2 -2
- package/js/src/coinbaseinternational.js +2 -1
- package/js/src/coinex.d.ts +1 -0
- package/js/src/coinex.js +74 -74
- package/js/src/coinmetro.d.ts +1 -1
- package/js/src/coinmetro.js +1 -1
- package/js/src/coinsph.js +1 -1
- package/js/src/cryptocom.d.ts +1 -0
- package/js/src/cryptocom.js +46 -48
- package/js/src/cryptomus.d.ts +2 -1
- package/js/src/cryptomus.js +43 -39
- package/js/src/deepcoin.js +3 -2
- package/js/src/delta.d.ts +1 -0
- package/js/src/delta.js +51 -52
- package/js/src/deribit.d.ts +1 -0
- package/js/src/deribit.js +31 -33
- package/js/src/derive.d.ts +1 -0
- package/js/src/derive.js +26 -28
- package/js/src/digifinex.d.ts +1 -0
- package/js/src/digifinex.js +43 -44
- package/js/src/exmo.d.ts +1 -0
- package/js/src/exmo.js +92 -83
- package/js/src/extended.d.ts +554 -0
- package/js/src/extended.js +3490 -0
- package/js/src/foxbit.d.ts +1 -0
- package/js/src/foxbit.js +71 -75
- package/js/src/gate.d.ts +1 -0
- package/js/src/gate.js +53 -53
- package/js/src/gemini.d.ts +2 -1
- package/js/src/gemini.js +41 -43
- package/js/src/grvt.js +4 -4
- package/js/src/hashkey.d.ts +1 -0
- package/js/src/hashkey.js +52 -54
- package/js/src/hitbtc.d.ts +0 -1
- package/js/src/hitbtc.js +3 -13
- package/js/src/hollaex.d.ts +1 -0
- package/js/src/hollaex.js +51 -54
- package/js/src/htx.d.ts +1 -0
- package/js/src/htx.js +75 -67
- package/js/src/hyperliquid.d.ts +1 -0
- package/js/src/hyperliquid.js +41 -42
- package/js/src/indodax.js +2 -2
- package/js/src/kraken.d.ts +2 -1
- package/js/src/kraken.js +57 -58
- package/js/src/kucoin.js +3 -2
- package/js/src/latoken.d.ts +1 -0
- package/js/src/latoken.js +30 -32
- package/js/src/lbank.d.ts +1 -0
- package/js/src/lbank.js +56 -56
- package/js/src/lighter.d.ts +1 -0
- package/js/src/lighter.js +35 -37
- package/js/src/luno.d.ts +1 -0
- package/js/src/luno.js +35 -43
- package/js/src/mexc.d.ts +2 -1
- package/js/src/mexc.js +48 -49
- package/js/src/modetrade.d.ts +1 -0
- package/js/src/modetrade.js +50 -52
- package/js/src/ndax.d.ts +1 -0
- package/js/src/ndax.js +35 -37
- package/js/src/okx.js +17 -2
- package/js/src/onetrading.d.ts +2 -1
- package/js/src/onetrading.js +21 -23
- package/js/src/phemex.d.ts +1 -0
- package/js/src/phemex.js +43 -45
- package/js/src/poloniex.js +17 -12
- package/js/src/pro/alpaca.js +1 -1
- package/js/src/pro/apex.js +1 -1
- package/js/src/pro/arkham.js +1 -1
- package/js/src/pro/backpack.js +1 -1
- package/js/src/pro/binance.js +3 -3
- package/js/src/pro/bitget.js +1 -1
- package/js/src/pro/bithumb.js +1 -1
- package/js/src/pro/bitstamp.js +1 -1
- package/js/src/pro/blockchaincom.js +1 -1
- package/js/src/pro/bybit.js +1 -1
- package/js/src/pro/cex.js +1 -1
- package/js/src/pro/coinex.js +1 -1
- package/js/src/pro/coinone.js +1 -1
- package/js/src/pro/cryptocom.js +3 -1
- package/js/src/pro/dydx.js +1 -1
- package/js/src/pro/exmo.js +1 -1
- package/js/src/pro/extended.d.ts +126 -0
- package/js/src/pro/extended.js +858 -0
- package/js/src/pro/gate.js +1 -1
- package/js/src/pro/independentreserve.js +1 -1
- package/js/src/pro/kucoin.js +1 -1
- package/js/src/pro/luno.d.ts +1 -1
- package/js/src/pro/luno.js +3 -3
- package/js/src/pro/onetrading.js +1 -1
- package/js/src/pro/toobit.js +1 -1
- package/js/src/pro/weex.js +1 -1
- package/js/src/tokocrypto.js +1 -1
- package/js/src/toobit.js +2 -2
- package/js/src/upbit.js +3 -3
- package/js/src/weex.d.ts +1 -0
- package/js/src/weex.js +57 -62
- package/js/src/whitebit.d.ts +1 -0
- package/js/src/whitebit.js +61 -63
- package/js/src/woo.d.ts +1 -0
- package/js/src/woo.js +65 -54
- package/js/src/woofipro.d.ts +1 -0
- package/js/src/woofipro.js +53 -47
- package/js/src/xt.js +1 -1
- package/js/src/zebpay.d.ts +2 -1
- package/js/src/zebpay.js +70 -72
- package/package.json +7 -7
- package/dist/cjs/src/gateio.js +0 -18
- package/dist/cjs/src/oxfun.js +0 -2933
- package/dist/cjs/src/pro/gateio.js +0 -18
- package/dist/cjs/src/pro/oxfun.js +0 -1113
- package/js/src/abstract/gateio.d.ts +0 -346
- package/js/src/abstract/gateio.js +0 -5
- package/js/src/abstract/oxfun.d.ts +0 -37
- package/js/src/gateio.d.ts +0 -4
- package/js/src/gateio.js +0 -11
- package/js/src/oxfun.d.ts +0 -442
- package/js/src/oxfun.js +0 -2926
- package/js/src/pro/gateio.d.ts +0 -4
- package/js/src/pro/gateio.js +0 -11
- package/js/src/pro/oxfun.d.ts +0 -234
- package/js/src/pro/oxfun.js +0 -1106
- /package/dist/cjs/src/abstract/{oxfun.js → extended.js} +0 -0
- /package/js/src/abstract/{oxfun.js → extended.js} +0 -0
|
@@ -0,0 +1,3497 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var extended$1 = require('./abstract/extended.js');
|
|
6
|
+
var Precise = require('./base/Precise.js');
|
|
7
|
+
var errors = require('./base/errors.js');
|
|
8
|
+
var number = require('./base/functions/number.js');
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/**
|
|
13
|
+
* @class extended
|
|
14
|
+
* @augments Exchange
|
|
15
|
+
*/
|
|
16
|
+
class extended extends extended$1["default"] {
|
|
17
|
+
describe() {
|
|
18
|
+
return this.deepExtend(super.describe(), {
|
|
19
|
+
'id': 'extended',
|
|
20
|
+
'name': 'Extended',
|
|
21
|
+
'countries': ['SG'],
|
|
22
|
+
'version': 'v2',
|
|
23
|
+
'rateLimit': 600,
|
|
24
|
+
'precisionMode': number.TICK_SIZE,
|
|
25
|
+
'certified': false,
|
|
26
|
+
'pro': true,
|
|
27
|
+
'dex': true,
|
|
28
|
+
'has': {
|
|
29
|
+
'CORS': undefined,
|
|
30
|
+
'spot': false,
|
|
31
|
+
'margin': false,
|
|
32
|
+
'swap': true,
|
|
33
|
+
'future': false,
|
|
34
|
+
'option': false,
|
|
35
|
+
'addMargin': false,
|
|
36
|
+
'borrowCrossMargin': false,
|
|
37
|
+
'borrowIsolatedMargin': false,
|
|
38
|
+
'cancelAllOrders': true,
|
|
39
|
+
'cancelAllOrdersAfter': true,
|
|
40
|
+
'cancelOrder': true,
|
|
41
|
+
'cancelOrders': true,
|
|
42
|
+
'closeAllPositions': false,
|
|
43
|
+
'closePosition': false,
|
|
44
|
+
'createConvertTrade': false,
|
|
45
|
+
'createDepositAddress': false,
|
|
46
|
+
'createMarketBuyOrderWithCost': false,
|
|
47
|
+
'createMarketOrderWithCost': false,
|
|
48
|
+
'createMarketSellOrderWithCost': false,
|
|
49
|
+
'createOrder': true,
|
|
50
|
+
'createOrders': false,
|
|
51
|
+
'createOrderWithTakeProfitAndStopLoss': false,
|
|
52
|
+
'createPostOnlyOrder': false,
|
|
53
|
+
'createReduceOnlyOrder': false,
|
|
54
|
+
'createStopLimitOrder': false,
|
|
55
|
+
'createStopLossOrder': false,
|
|
56
|
+
'createStopMarketOrder': false,
|
|
57
|
+
'createStopOrder': false,
|
|
58
|
+
'createTakeProfitOrder': false,
|
|
59
|
+
'createTrailingAmountOrder': false,
|
|
60
|
+
'createTrailingPercentOrder': false,
|
|
61
|
+
'createTriggerOrder': false,
|
|
62
|
+
'editOrder': true,
|
|
63
|
+
'fetchAccounts': true,
|
|
64
|
+
'fetchBalance': true,
|
|
65
|
+
'fetchBorrowInterest': false,
|
|
66
|
+
'fetchBorrowRateHistories': false,
|
|
67
|
+
'fetchBorrowRateHistory': false,
|
|
68
|
+
'fetchCanceledAndClosedOrders': false,
|
|
69
|
+
'fetchCanceledOrders': true,
|
|
70
|
+
'fetchClosedOrders': true,
|
|
71
|
+
'fetchConvertCurrencies': false,
|
|
72
|
+
'fetchConvertQuote': false,
|
|
73
|
+
'fetchConvertTrade': false,
|
|
74
|
+
'fetchConvertTradeHistory': false,
|
|
75
|
+
'fetchCrossBorrowRate': false,
|
|
76
|
+
'fetchCrossBorrowRates': false,
|
|
77
|
+
'fetchCurrencies': true,
|
|
78
|
+
'fetchDeposit': false,
|
|
79
|
+
'fetchDepositAddress': false,
|
|
80
|
+
'fetchDepositAddresses': false,
|
|
81
|
+
'fetchDepositAddressesByNetwork': false,
|
|
82
|
+
'fetchDeposits': true,
|
|
83
|
+
'fetchDepositsWithdrawals': false,
|
|
84
|
+
'fetchDepositWithdrawFee': false,
|
|
85
|
+
'fetchDepositWithdrawFees': false,
|
|
86
|
+
'fetchFundingHistory': true,
|
|
87
|
+
'fetchFundingInterval': false,
|
|
88
|
+
'fetchFundingIntervals': false,
|
|
89
|
+
'fetchFundingRate': false,
|
|
90
|
+
'fetchFundingRateHistory': true,
|
|
91
|
+
'fetchFundingRates': false,
|
|
92
|
+
'fetchIndexOHLCV': true,
|
|
93
|
+
'fetchIsolatedBorrowRate': false,
|
|
94
|
+
'fetchIsolatedBorrowRates': false,
|
|
95
|
+
'fetchLedger': true,
|
|
96
|
+
'fetchLeverage': true,
|
|
97
|
+
'fetchLeverageTiers': false,
|
|
98
|
+
'fetchLiquidations': false,
|
|
99
|
+
'fetchLongShortRatio': false,
|
|
100
|
+
'fetchLongShortRatioHistory': false,
|
|
101
|
+
'fetchMarginAdjustmentHistory': false,
|
|
102
|
+
'fetchMarginMode': false,
|
|
103
|
+
'fetchMarketLeverageTiers': false,
|
|
104
|
+
'fetchMarkets': true,
|
|
105
|
+
'fetchMarkOHLCV': true,
|
|
106
|
+
'fetchMarkPrice': false,
|
|
107
|
+
'fetchMyLiquidations': false,
|
|
108
|
+
'fetchMyTrades': true,
|
|
109
|
+
'fetchOHLCV': true,
|
|
110
|
+
'fetchOpenInterest': false,
|
|
111
|
+
'fetchOpenInterestHistory': true,
|
|
112
|
+
'fetchOpenOrders': true,
|
|
113
|
+
'fetchOrder': true,
|
|
114
|
+
'fetchOrderBook': true,
|
|
115
|
+
'fetchOrderBooks': false,
|
|
116
|
+
'fetchOrders': true,
|
|
117
|
+
'fetchOrderTrades': false,
|
|
118
|
+
'fetchPosition': true,
|
|
119
|
+
'fetchPositionHistory': false,
|
|
120
|
+
'fetchPositionMode': false,
|
|
121
|
+
'fetchPositions': true,
|
|
122
|
+
'fetchPositionsHistory': true,
|
|
123
|
+
'fetchPositionsRisk': false,
|
|
124
|
+
'fetchPremiumIndexOHLCV': false,
|
|
125
|
+
'fetchStatus': false,
|
|
126
|
+
'fetchTicker': true,
|
|
127
|
+
'fetchTickers': true,
|
|
128
|
+
'fetchTime': false,
|
|
129
|
+
'fetchTrades': true,
|
|
130
|
+
'fetchTradingFee': true,
|
|
131
|
+
'fetchTradingFees': true,
|
|
132
|
+
'fetchTransactions': true,
|
|
133
|
+
'fetchTransfer': false,
|
|
134
|
+
'fetchTransfers': true,
|
|
135
|
+
'fetchWithdrawAddresses': false,
|
|
136
|
+
'fetchWithdrawal': false,
|
|
137
|
+
'fetchWithdrawals': true,
|
|
138
|
+
'reduceMargin': false,
|
|
139
|
+
'repayCrossMargin': false,
|
|
140
|
+
'repayIsolatedMargin': false,
|
|
141
|
+
'setLeverage': true,
|
|
142
|
+
'setMargin': false,
|
|
143
|
+
'setMarginMode': false,
|
|
144
|
+
'setPositionMode': false,
|
|
145
|
+
'signIn': false,
|
|
146
|
+
'transfer': true,
|
|
147
|
+
'withdraw': true,
|
|
148
|
+
},
|
|
149
|
+
'features': {},
|
|
150
|
+
'timeframes': {
|
|
151
|
+
'1m': 'PT1M',
|
|
152
|
+
'5m': 'PT5M',
|
|
153
|
+
'15m': 'PT15M',
|
|
154
|
+
'30m': 'PT30M',
|
|
155
|
+
'1h': 'PT1H',
|
|
156
|
+
'2h': 'PT2H',
|
|
157
|
+
'4h': 'PT4H',
|
|
158
|
+
'8h': 'PT8H',
|
|
159
|
+
'12h': 'PT12H',
|
|
160
|
+
'1d': 'PT24H',
|
|
161
|
+
'1w': 'P7D',
|
|
162
|
+
'1M': 'P30D',
|
|
163
|
+
},
|
|
164
|
+
'hostname': 'extended.exchange',
|
|
165
|
+
'urls': {
|
|
166
|
+
'logo': 'https://github.com/user-attachments/assets/309d44db-2a50-4529-a27f-8f4492aec299',
|
|
167
|
+
'api': {
|
|
168
|
+
'rest': 'https://api.starknet.{hostname}',
|
|
169
|
+
},
|
|
170
|
+
'test': {
|
|
171
|
+
'rest': 'https://api.starknet.sepolia.{hostname}',
|
|
172
|
+
},
|
|
173
|
+
'www': 'https://app.{hostname}',
|
|
174
|
+
'doc': 'https://api.docs.{hostname}',
|
|
175
|
+
'fees': 'https://docs.{hostname}/extended-resources/trading/trading-fees-and-rebates',
|
|
176
|
+
'referral': '',
|
|
177
|
+
},
|
|
178
|
+
'api': {
|
|
179
|
+
'v1': {
|
|
180
|
+
'public': {
|
|
181
|
+
'get': [
|
|
182
|
+
'info/markets',
|
|
183
|
+
'info/assets',
|
|
184
|
+
'info/assets/{asset}/price',
|
|
185
|
+
'info/markets/{market}/stats',
|
|
186
|
+
'info/markets/{market}/orderbook',
|
|
187
|
+
'info/markets/{market}/trades',
|
|
188
|
+
'info/candles/{market}/{candleType}',
|
|
189
|
+
'info/{market}/funding',
|
|
190
|
+
'info/{market}/open-interests',
|
|
191
|
+
'info/builder/dashboard',
|
|
192
|
+
],
|
|
193
|
+
},
|
|
194
|
+
'private': {
|
|
195
|
+
'get': [
|
|
196
|
+
'user/accounts',
|
|
197
|
+
'user/account/info',
|
|
198
|
+
'user/balance',
|
|
199
|
+
'user/spot/balances',
|
|
200
|
+
'user/assetOperations',
|
|
201
|
+
'user/positions',
|
|
202
|
+
'user/positions/history',
|
|
203
|
+
'user/orders',
|
|
204
|
+
'user/orders/history',
|
|
205
|
+
'user/orders/{id}',
|
|
206
|
+
'user/orders/external/{externalId}',
|
|
207
|
+
'user/trades',
|
|
208
|
+
'user/funding/history',
|
|
209
|
+
'user/rebates/stats',
|
|
210
|
+
'user/leverage',
|
|
211
|
+
'user/fees',
|
|
212
|
+
'user/bridge/config',
|
|
213
|
+
'user/bridge/quote',
|
|
214
|
+
'user/affiliate',
|
|
215
|
+
'user/referrals/status',
|
|
216
|
+
'user/referrals/links',
|
|
217
|
+
'user/referrals/dashboard',
|
|
218
|
+
'user/rewards/earned',
|
|
219
|
+
'user/rewards/leaderboard/stats',
|
|
220
|
+
'portfolio/charts/equities',
|
|
221
|
+
'portfolio/charts/pnl',
|
|
222
|
+
'vault/public/performance',
|
|
223
|
+
'vault/public/summary',
|
|
224
|
+
'builder/trades',
|
|
225
|
+
],
|
|
226
|
+
'post': [
|
|
227
|
+
'user/order',
|
|
228
|
+
'user/order/massCancel',
|
|
229
|
+
'user/deadmanswitch',
|
|
230
|
+
'user/bridge/quote',
|
|
231
|
+
'user/withdrawal',
|
|
232
|
+
'user/transfer',
|
|
233
|
+
'user/referrals/use',
|
|
234
|
+
'user/referrals',
|
|
235
|
+
],
|
|
236
|
+
'put': [
|
|
237
|
+
'user/referrals',
|
|
238
|
+
],
|
|
239
|
+
'patch': [
|
|
240
|
+
'user/leverage',
|
|
241
|
+
],
|
|
242
|
+
'delete': [
|
|
243
|
+
'user/order/{id}',
|
|
244
|
+
'user/order',
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
'fees': {
|
|
250
|
+
'taker': this.parseNumber('0.002'),
|
|
251
|
+
'maker': this.parseNumber('0.002'),
|
|
252
|
+
},
|
|
253
|
+
'requiredCredentials': {
|
|
254
|
+
'apiKey': true,
|
|
255
|
+
'secret': false,
|
|
256
|
+
'privateKey': true,
|
|
257
|
+
},
|
|
258
|
+
'exceptions': {
|
|
259
|
+
'exact': {
|
|
260
|
+
'1000': errors.InvalidOrder,
|
|
261
|
+
'1001': errors.InvalidOrder,
|
|
262
|
+
'1002': errors.InvalidOrder,
|
|
263
|
+
'1003': errors.InvalidOrder,
|
|
264
|
+
'1004': errors.InvalidOrder,
|
|
265
|
+
'1005': errors.InvalidOrder,
|
|
266
|
+
'1006': errors.ExchangeError,
|
|
267
|
+
'1008': errors.InvalidOrder,
|
|
268
|
+
'1009': errors.InvalidOrder,
|
|
269
|
+
'1010': errors.ExchangeError,
|
|
270
|
+
'1011': errors.InvalidOrder,
|
|
271
|
+
'1012': errors.InvalidOrder,
|
|
272
|
+
'1013': errors.InvalidOrder,
|
|
273
|
+
'1014': errors.InvalidOrder,
|
|
274
|
+
'1049': errors.InvalidOrder,
|
|
275
|
+
'1050': errors.InvalidOrder,
|
|
276
|
+
'10501': errors.InvalidOrder,
|
|
277
|
+
'1052': errors.InvalidOrder,
|
|
278
|
+
'1053': errors.InvalidOrder,
|
|
279
|
+
'1100': errors.InvalidOrder,
|
|
280
|
+
'1101': errors.InvalidOrder,
|
|
281
|
+
'1102': errors.InvalidOrder,
|
|
282
|
+
'1120': errors.InvalidOrder,
|
|
283
|
+
'1121': errors.InvalidOrder,
|
|
284
|
+
'1122': errors.InvalidOrder,
|
|
285
|
+
'1123': errors.InvalidOrder,
|
|
286
|
+
'1124': errors.InvalidOrder,
|
|
287
|
+
'1125': errors.InvalidOrder,
|
|
288
|
+
'1126': errors.InvalidOrder,
|
|
289
|
+
'1127': errors.InvalidOrder,
|
|
290
|
+
'1128': errors.InvalidOrder,
|
|
291
|
+
'1129': errors.InvalidOrder,
|
|
292
|
+
'1130': errors.InvalidOrder,
|
|
293
|
+
'1131': errors.InvalidOrder,
|
|
294
|
+
'1132': errors.InvalidOrder,
|
|
295
|
+
'1133': errors.InvalidOrder,
|
|
296
|
+
'1134': errors.InvalidOrder,
|
|
297
|
+
'1135': errors.InvalidOrder,
|
|
298
|
+
'1136': errors.InvalidOrder,
|
|
299
|
+
'1137': errors.InvalidOrder,
|
|
300
|
+
'1138': errors.InvalidOrder,
|
|
301
|
+
'1139': errors.InvalidOrder,
|
|
302
|
+
'1140': errors.InsufficientFunds,
|
|
303
|
+
'1141': errors.InvalidOrder,
|
|
304
|
+
'1142': errors.InvalidOrder,
|
|
305
|
+
'1143': errors.InvalidOrder,
|
|
306
|
+
'1144': errors.InvalidOrder,
|
|
307
|
+
'1145': errors.InvalidOrder,
|
|
308
|
+
'1146': errors.InvalidOrder,
|
|
309
|
+
'1147': errors.InvalidOrder,
|
|
310
|
+
'1148': errors.InvalidOrder,
|
|
311
|
+
'1500': errors.InvalidOrder,
|
|
312
|
+
'1600': errors.BadRequest,
|
|
313
|
+
'1601': errors.BadRequest,
|
|
314
|
+
'1602': errors.BadRequest,
|
|
315
|
+
'1604': errors.BadRequest,
|
|
316
|
+
'1605': errors.BadRequest,
|
|
317
|
+
'1607': errors.BadRequest,
|
|
318
|
+
'1608': errors.BadRequest,
|
|
319
|
+
'1650': errors.BadRequest,
|
|
320
|
+
'1700': errors.BadRequest,
|
|
321
|
+
'1701': errors.BadRequest,
|
|
322
|
+
'1703': errors.BadRequest,
|
|
323
|
+
'1704': errors.BadRequest, // Referral code already applied.
|
|
324
|
+
},
|
|
325
|
+
'broad': {},
|
|
326
|
+
},
|
|
327
|
+
'options': {
|
|
328
|
+
'builderFee': true,
|
|
329
|
+
'builderFeeRate': '0.0001',
|
|
330
|
+
'builderId': '257624',
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
async loadMarkets(reload = false, params = {}) {
|
|
335
|
+
const markets = await super.loadMarkets(reload, params);
|
|
336
|
+
const currenciesByNumericId = this.safeDict(this.options, 'currenciesByNumericId');
|
|
337
|
+
if ((currenciesByNumericId === undefined) || reload) {
|
|
338
|
+
this.options['currenciesByNumericId'] = this.indexByStringifiedNumericId(this.currencies);
|
|
339
|
+
}
|
|
340
|
+
return markets;
|
|
341
|
+
}
|
|
342
|
+
indexByStringifiedNumericId(input) {
|
|
343
|
+
const result = {};
|
|
344
|
+
if (input === undefined) {
|
|
345
|
+
return undefined;
|
|
346
|
+
}
|
|
347
|
+
const keys = Object.keys(input);
|
|
348
|
+
for (let i = 0; i < keys.length; i++) {
|
|
349
|
+
const key = keys[i];
|
|
350
|
+
const item = input[key];
|
|
351
|
+
const numericIdString = this.safeString(item, 'numericId');
|
|
352
|
+
if (numericIdString === undefined) {
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
result[numericIdString] = item;
|
|
356
|
+
}
|
|
357
|
+
return result;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* @method
|
|
361
|
+
* @name extended#fetchMarkets
|
|
362
|
+
* @description retrieves data on all markets for extended
|
|
363
|
+
* @see https://api.docs.extended.exchange/#get-markets
|
|
364
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
365
|
+
* @returns {object[]} an array of objects representing market data
|
|
366
|
+
*/
|
|
367
|
+
async fetchMarkets(params = {}) {
|
|
368
|
+
const response = await this.v1PublicGetInfoMarkets(params);
|
|
369
|
+
//
|
|
370
|
+
// {
|
|
371
|
+
// "status": "OK",
|
|
372
|
+
// "data": [
|
|
373
|
+
// {
|
|
374
|
+
// "name": "BTC-USD",
|
|
375
|
+
// "uiName": "BTC-USD",
|
|
376
|
+
// "category": "Crypto",
|
|
377
|
+
// "subCategory": "L1",
|
|
378
|
+
// "assetName": "BTC",
|
|
379
|
+
// "assetPrecision": 5,
|
|
380
|
+
// "collateralAssetName": "USD",
|
|
381
|
+
// "collateralAssetPrecision": 6,
|
|
382
|
+
// "description": "Bitcoin",
|
|
383
|
+
// "active": true,
|
|
384
|
+
// "status": "ACTIVE",
|
|
385
|
+
// "marketStats": {
|
|
386
|
+
// "dailyVolume": "231016077.512960",
|
|
387
|
+
// "dailyVolumeBase": "3025.00058",
|
|
388
|
+
// "dailyPriceChange": "420",
|
|
389
|
+
// "dailyPriceChangePercentage": "0.0055",
|
|
390
|
+
// "dailyLow": "75635",
|
|
391
|
+
// "dailyHigh": "77399",
|
|
392
|
+
// "lastPrice": "77259",
|
|
393
|
+
// "askPrice": "77260",
|
|
394
|
+
// "bidPrice": "77259",
|
|
395
|
+
// "markPrice": "77259.680250000004",
|
|
396
|
+
// "indexPrice": "77299.020412500001",
|
|
397
|
+
// "fundingRate": "0.000013",
|
|
398
|
+
// "nextFundingRate": 1777442400000,
|
|
399
|
+
// "openInterest": "115861923.311902",
|
|
400
|
+
// "openInterestBase": "1500.40958",
|
|
401
|
+
// "deleverageLevels": {
|
|
402
|
+
// "shortPositions": [
|
|
403
|
+
// {
|
|
404
|
+
// "level": 1,
|
|
405
|
+
// "rankingLowerBound": "-815.7788"
|
|
406
|
+
// },
|
|
407
|
+
// {
|
|
408
|
+
// "level": 2,
|
|
409
|
+
// "rankingLowerBound": "-2.1328"
|
|
410
|
+
// },
|
|
411
|
+
// {
|
|
412
|
+
// "level": 3,
|
|
413
|
+
// "rankingLowerBound": "-0.9297"
|
|
414
|
+
// },
|
|
415
|
+
// {
|
|
416
|
+
// "level": 4,
|
|
417
|
+
// "rankingLowerBound": "0.0000"
|
|
418
|
+
// }
|
|
419
|
+
// ],
|
|
420
|
+
// "longPositions": [
|
|
421
|
+
// {
|
|
422
|
+
// "level": 1,
|
|
423
|
+
// "rankingLowerBound": "-47234.9095"
|
|
424
|
+
// },
|
|
425
|
+
// {
|
|
426
|
+
// "level": 2,
|
|
427
|
+
// "rankingLowerBound": "-0.0030"
|
|
428
|
+
// },
|
|
429
|
+
// {
|
|
430
|
+
// "level": 3,
|
|
431
|
+
// "rankingLowerBound": "0.0020"
|
|
432
|
+
// },
|
|
433
|
+
// {
|
|
434
|
+
// "level": 4,
|
|
435
|
+
// "rankingLowerBound": "0.0033"
|
|
436
|
+
// }
|
|
437
|
+
// ]
|
|
438
|
+
// }
|
|
439
|
+
// },
|
|
440
|
+
// "tradingConfig": {
|
|
441
|
+
// "minOrderSize": "0.0001",
|
|
442
|
+
// "minOrderSizeChange": "0.00001",
|
|
443
|
+
// "minPriceChange": "1",
|
|
444
|
+
// "maxMarketOrderValue": "3000000",
|
|
445
|
+
// "maxLimitOrderValue": "15000000",
|
|
446
|
+
// "maxPositionValue": "60000000",
|
|
447
|
+
// "maxLeverage": "50.00",
|
|
448
|
+
// "hourlyFundingRateCap": "0.25",
|
|
449
|
+
// "maxNumOrders": "200",
|
|
450
|
+
// "limitPriceCap": "0.05",
|
|
451
|
+
// "limitPriceFloor": "0.05",
|
|
452
|
+
// "riskFactorConfig": [
|
|
453
|
+
// {
|
|
454
|
+
// "upperBound": "4000000",
|
|
455
|
+
// "riskFactor": "0.02",
|
|
456
|
+
// "isAvailableForUsers": true
|
|
457
|
+
// }
|
|
458
|
+
// ]
|
|
459
|
+
// },
|
|
460
|
+
// "l2Config": {
|
|
461
|
+
// "type": "STARKX",
|
|
462
|
+
// "collateralId": "0x1",
|
|
463
|
+
// "syntheticId": "0x4254432d3600000000000000000000",
|
|
464
|
+
// "syntheticResolution": 1000000,
|
|
465
|
+
// "collateralResolution": 1000000
|
|
466
|
+
// },
|
|
467
|
+
// "visibleOnUi": true,
|
|
468
|
+
// "createdAt": 1752829532673
|
|
469
|
+
// }
|
|
470
|
+
// ]
|
|
471
|
+
// }
|
|
472
|
+
//
|
|
473
|
+
const data = this.safeList(response, 'data', []);
|
|
474
|
+
return this.parseMarkets(data);
|
|
475
|
+
}
|
|
476
|
+
parseMarket(market) {
|
|
477
|
+
//
|
|
478
|
+
// {
|
|
479
|
+
// "name": "BTC-USD",
|
|
480
|
+
// "uiName": "BTC-USD",
|
|
481
|
+
// "category": "Crypto",
|
|
482
|
+
// "subCategory": "L1",
|
|
483
|
+
// "assetName": "BTC",
|
|
484
|
+
// "assetPrecision": 5,
|
|
485
|
+
// "collateralAssetName": "USD",
|
|
486
|
+
// "collateralAssetPrecision": 6,
|
|
487
|
+
// "description": "Bitcoin",
|
|
488
|
+
// "active": true,
|
|
489
|
+
// "status": "ACTIVE",
|
|
490
|
+
// "marketStats": { ... },
|
|
491
|
+
// "tradingConfig": {
|
|
492
|
+
// "minOrderSize": "0.0001",
|
|
493
|
+
// "minOrderSizeChange": "0.00001",
|
|
494
|
+
// "minPriceChange": "1",
|
|
495
|
+
// "maxMarketOrderValue": "3000000",
|
|
496
|
+
// "maxLimitOrderValue": "15000000",
|
|
497
|
+
// "maxPositionValue": "60000000",
|
|
498
|
+
// "maxLeverage": "50.00",
|
|
499
|
+
// "hourlyFundingRateCap": "0.25",
|
|
500
|
+
// "maxNumOrders": "200",
|
|
501
|
+
// "limitPriceCap": "0.05",
|
|
502
|
+
// "limitPriceFloor": "0.05",
|
|
503
|
+
// "riskFactorConfig": [
|
|
504
|
+
// {
|
|
505
|
+
// "upperBound": "4000000",
|
|
506
|
+
// "riskFactor": "0.02",
|
|
507
|
+
// "isAvailableForUsers": true
|
|
508
|
+
// }
|
|
509
|
+
// ]
|
|
510
|
+
// },
|
|
511
|
+
// "l2Config": { ... },
|
|
512
|
+
// "visibleOnUi": true,
|
|
513
|
+
// "createdAt": 1752829532673
|
|
514
|
+
// }
|
|
515
|
+
//
|
|
516
|
+
const tradingConfig = this.safeDict(market, 'tradingConfig', {});
|
|
517
|
+
const marketId = this.safeString(market, 'name');
|
|
518
|
+
let baseId = this.safeString(market, 'assetName');
|
|
519
|
+
if (baseId.indexOf('SPOT') >= 0) {
|
|
520
|
+
baseId = baseId.replace('SPOT', '');
|
|
521
|
+
}
|
|
522
|
+
const quoteId = this.safeString(market, 'collateralAssetName');
|
|
523
|
+
const base = this.safeCurrencyCode(baseId);
|
|
524
|
+
let quote = this.safeCurrencyCode(quoteId);
|
|
525
|
+
if (quoteId === 'USD') {
|
|
526
|
+
quote = 'USDC';
|
|
527
|
+
}
|
|
528
|
+
const status = this.safeString(market, 'status');
|
|
529
|
+
const active = (status === 'ACTIVE');
|
|
530
|
+
const amountPrecision = this.safeNumber(tradingConfig, 'minOrderSizeChange');
|
|
531
|
+
const pricePrecision = this.safeNumber(tradingConfig, 'minPriceChange');
|
|
532
|
+
const maxLeverage = this.safeNumber(tradingConfig, 'maxLeverage');
|
|
533
|
+
const minAmount = this.safeNumber(tradingConfig, 'minOrderSize');
|
|
534
|
+
const maxCost = this.safeNumber(tradingConfig, 'maxLimitOrderValue');
|
|
535
|
+
const created = this.safeInteger(market, 'createdAt');
|
|
536
|
+
let settleId = undefined;
|
|
537
|
+
let settle = undefined;
|
|
538
|
+
let symbol = base + '/' + quote;
|
|
539
|
+
let isSpot = false;
|
|
540
|
+
let type = this.safeStringLower(market, 'type');
|
|
541
|
+
let contractSize = undefined;
|
|
542
|
+
let linear = undefined;
|
|
543
|
+
let inverse = undefined;
|
|
544
|
+
if (type === 'spot') {
|
|
545
|
+
isSpot = true;
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
type = 'swap';
|
|
549
|
+
settleId = quoteId;
|
|
550
|
+
settle = quote;
|
|
551
|
+
symbol += ':' + settle;
|
|
552
|
+
contractSize = this.parseNumber('1');
|
|
553
|
+
linear = true;
|
|
554
|
+
inverse = false;
|
|
555
|
+
}
|
|
556
|
+
return this.safeMarketStructure({
|
|
557
|
+
'id': marketId,
|
|
558
|
+
'symbol': symbol,
|
|
559
|
+
'base': base,
|
|
560
|
+
'quote': quote,
|
|
561
|
+
'settle': settle,
|
|
562
|
+
'baseId': baseId,
|
|
563
|
+
'quoteId': quoteId,
|
|
564
|
+
'settleId': settleId,
|
|
565
|
+
'type': type,
|
|
566
|
+
'spot': isSpot,
|
|
567
|
+
'margin': false,
|
|
568
|
+
'swap': !isSpot,
|
|
569
|
+
'future': false,
|
|
570
|
+
'option': false,
|
|
571
|
+
'active': active,
|
|
572
|
+
'contract': !isSpot,
|
|
573
|
+
'linear': linear,
|
|
574
|
+
'inverse': inverse,
|
|
575
|
+
'taker': this.safeNumber(this.fees, 'taker'),
|
|
576
|
+
'maker': this.safeNumber(this.fees, 'maker'),
|
|
577
|
+
'contractSize': contractSize,
|
|
578
|
+
'expiry': undefined,
|
|
579
|
+
'expiryDatetime': undefined,
|
|
580
|
+
'strike': undefined,
|
|
581
|
+
'optionType': undefined,
|
|
582
|
+
'precision': {
|
|
583
|
+
'amount': amountPrecision,
|
|
584
|
+
'price': pricePrecision,
|
|
585
|
+
},
|
|
586
|
+
'limits': {
|
|
587
|
+
'leverage': {
|
|
588
|
+
'min': this.parseNumber('1'),
|
|
589
|
+
'max': maxLeverage,
|
|
590
|
+
},
|
|
591
|
+
'amount': {
|
|
592
|
+
'min': minAmount,
|
|
593
|
+
'max': undefined,
|
|
594
|
+
},
|
|
595
|
+
'price': {
|
|
596
|
+
'min': undefined,
|
|
597
|
+
'max': undefined,
|
|
598
|
+
},
|
|
599
|
+
'cost': {
|
|
600
|
+
'min': undefined,
|
|
601
|
+
'max': maxCost,
|
|
602
|
+
},
|
|
603
|
+
},
|
|
604
|
+
'created': created,
|
|
605
|
+
'info': market,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* @method
|
|
610
|
+
* @name extended#fetchCurrencies
|
|
611
|
+
* @description fetches all available currencies on an exchange
|
|
612
|
+
* @see https://api.docs.extended.exchange/#get-assets
|
|
613
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
614
|
+
* @returns {object} an associative dictionary of currencies
|
|
615
|
+
*/
|
|
616
|
+
async fetchCurrencies(params = {}) {
|
|
617
|
+
const response = await this.v1PublicGetInfoAssets(params);
|
|
618
|
+
//
|
|
619
|
+
// {
|
|
620
|
+
// "status": "OK",
|
|
621
|
+
// "data": [
|
|
622
|
+
// {
|
|
623
|
+
// "id": 1,
|
|
624
|
+
// "name": "USD",
|
|
625
|
+
// "symbol": "USD",
|
|
626
|
+
// "description": "USD Collateral",
|
|
627
|
+
// "precision": 6,
|
|
628
|
+
// "isActive": true,
|
|
629
|
+
// "isCollateral": true,
|
|
630
|
+
// "starkexId": "0x1",
|
|
631
|
+
// "starkexResolution": 1000000,
|
|
632
|
+
// "l1Id": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
633
|
+
// "l1Resolution": 1000000,
|
|
634
|
+
// "version": 3,
|
|
635
|
+
// "createdAt": 1752829532673,
|
|
636
|
+
// "type": "SPOT",
|
|
637
|
+
// "canBeUsedAsCollateral": true,
|
|
638
|
+
// "riskFactors": [],
|
|
639
|
+
// "availableForTradeFactors": []
|
|
640
|
+
// }
|
|
641
|
+
// ]
|
|
642
|
+
// }
|
|
643
|
+
//
|
|
644
|
+
const data = this.safeList(response, 'data', []);
|
|
645
|
+
return this.parseCurrencies(data);
|
|
646
|
+
}
|
|
647
|
+
parseCurrency(currency) {
|
|
648
|
+
//
|
|
649
|
+
// {
|
|
650
|
+
// "id": 1,
|
|
651
|
+
// "name": "USD",
|
|
652
|
+
// "symbol": "USD",
|
|
653
|
+
// "description": "USD Collateral",
|
|
654
|
+
// "precision": 6,
|
|
655
|
+
// "isActive": true,
|
|
656
|
+
// "isCollateral": true,
|
|
657
|
+
// "starkexId": "0x1",
|
|
658
|
+
// "starkexResolution": 1000000,
|
|
659
|
+
// "l1Id": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
|
|
660
|
+
// "l1Resolution": 1000000,
|
|
661
|
+
// "version": 3,
|
|
662
|
+
// "createdAt": 1752829532673,
|
|
663
|
+
// "type": "SPOT",
|
|
664
|
+
// "canBeUsedAsCollateral": true,
|
|
665
|
+
// "riskFactors": [],
|
|
666
|
+
// "availableForTradeFactors": []
|
|
667
|
+
// }
|
|
668
|
+
//
|
|
669
|
+
let currencyId = this.safeString(currency, 'symbol');
|
|
670
|
+
if ((currencyId !== undefined) && (currencyId.indexOf('SPOT') >= 0)) {
|
|
671
|
+
currencyId = currencyId.replace('SPOT', '');
|
|
672
|
+
}
|
|
673
|
+
let code = this.safeCurrencyCode(currencyId);
|
|
674
|
+
if (currencyId === 'USD') {
|
|
675
|
+
code = 'USDC';
|
|
676
|
+
}
|
|
677
|
+
const name = this.safeString(currency, 'name');
|
|
678
|
+
const precision = this.safeInteger(currency, 'precision');
|
|
679
|
+
const isActive = this.safeBool(currency, 'isActive');
|
|
680
|
+
return this.safeCurrencyStructure({
|
|
681
|
+
'id': currencyId,
|
|
682
|
+
'code': code,
|
|
683
|
+
'numericId': this.safeInteger(currency, 'id'),
|
|
684
|
+
'name': name,
|
|
685
|
+
'active': isActive,
|
|
686
|
+
'deposit': true,
|
|
687
|
+
'withdraw': true,
|
|
688
|
+
'precision': Math.pow(10, precision * -1),
|
|
689
|
+
'type': 'other',
|
|
690
|
+
'margin': this.safeBool(currency, 'canBeUsedAsCollateral'),
|
|
691
|
+
'info': currency,
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* @method
|
|
696
|
+
* @name extended#fetchTicker
|
|
697
|
+
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
698
|
+
* @see https://api.docs.extended.exchange/#get-market-statistics
|
|
699
|
+
* @param {string} symbol unified symbol of the market to fetch the ticker for
|
|
700
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
701
|
+
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
702
|
+
*/
|
|
703
|
+
async fetchTicker(symbol, params = {}) {
|
|
704
|
+
await this.loadMarkets();
|
|
705
|
+
const market = this.market(symbol);
|
|
706
|
+
const request = {
|
|
707
|
+
'market': market['id'],
|
|
708
|
+
};
|
|
709
|
+
const response = await this.v1PublicGetInfoMarketsMarketStats(this.extend(request, params));
|
|
710
|
+
//
|
|
711
|
+
// {
|
|
712
|
+
// "status": "OK",
|
|
713
|
+
// "data": {
|
|
714
|
+
// "dailyVolume": "231216165.666600",
|
|
715
|
+
// "dailyVolumeBase": "3027.36710",
|
|
716
|
+
// "dailyPriceChange": "181",
|
|
717
|
+
// "dailyPriceChangePercentage": "0.0024",
|
|
718
|
+
// "dailyLow": "75635",
|
|
719
|
+
// "dailyHigh": "77399",
|
|
720
|
+
// "lastPrice": "77026",
|
|
721
|
+
// "askPrice": "77026",
|
|
722
|
+
// "bidPrice": "77025",
|
|
723
|
+
// "markPrice": "77006.091897999984",
|
|
724
|
+
// "indexPrice": "77050.739529925005",
|
|
725
|
+
// "fundingRate": "0.000012",
|
|
726
|
+
// "nextFundingRate": 1777446000000,
|
|
727
|
+
// "openInterest": "114851569.088316",
|
|
728
|
+
// "openInterestBase": "1491.33012",
|
|
729
|
+
// "deleverageLevels": {
|
|
730
|
+
// "shortPositions": [
|
|
731
|
+
// { "level": 1, "rankingLowerBound": "-784.2884" },
|
|
732
|
+
// { "level": 2, "rankingLowerBound": "-2.1078" },
|
|
733
|
+
// { "level": 3, "rankingLowerBound": "-0.8754" },
|
|
734
|
+
// { "level": 4, "rankingLowerBound": "0.0000" }
|
|
735
|
+
// ],
|
|
736
|
+
// "longPositions": [
|
|
737
|
+
// { "level": 1, "rankingLowerBound": "-47747.2010" },
|
|
738
|
+
// { "level": 2, "rankingLowerBound": "-0.0131" },
|
|
739
|
+
// { "level": 3, "rankingLowerBound": "0.0019" },
|
|
740
|
+
// { "level": 4, "rankingLowerBound": "0.0032" }
|
|
741
|
+
// ]
|
|
742
|
+
// }
|
|
743
|
+
// }
|
|
744
|
+
// }
|
|
745
|
+
//
|
|
746
|
+
const data = this.safeDict(response, 'data', {});
|
|
747
|
+
return this.parseTicker(data, market);
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* @method
|
|
751
|
+
* @name extended#fetchTickers
|
|
752
|
+
* @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for all markets
|
|
753
|
+
* @see https://api.docs.extended.exchange/#get-markets
|
|
754
|
+
* @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
|
755
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
756
|
+
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
|
|
757
|
+
*/
|
|
758
|
+
async fetchTickers(symbols = undefined, params = {}) {
|
|
759
|
+
await this.loadMarkets();
|
|
760
|
+
symbols = this.marketSymbols(symbols);
|
|
761
|
+
const request = {};
|
|
762
|
+
if (symbols !== undefined) {
|
|
763
|
+
const marketIds = [];
|
|
764
|
+
for (let i = 0; i < symbols.length; i++) {
|
|
765
|
+
const market = this.market(symbols[i]);
|
|
766
|
+
marketIds.push(market['id']);
|
|
767
|
+
}
|
|
768
|
+
request['market'] = marketIds;
|
|
769
|
+
}
|
|
770
|
+
const response = await this.v1PublicGetInfoMarkets(this.extend(request, params));
|
|
771
|
+
//
|
|
772
|
+
// {
|
|
773
|
+
// "status": "OK",
|
|
774
|
+
// "data": [
|
|
775
|
+
// {
|
|
776
|
+
// "name": "BTC-USD",
|
|
777
|
+
// "assetName": "BTC",
|
|
778
|
+
// "collateralAssetName": "USD",
|
|
779
|
+
// "marketStats": {
|
|
780
|
+
// "dailyVolume": "231016077.512960",
|
|
781
|
+
// ...
|
|
782
|
+
// },
|
|
783
|
+
// ...
|
|
784
|
+
// }
|
|
785
|
+
// ]
|
|
786
|
+
// }
|
|
787
|
+
//
|
|
788
|
+
const data = this.safeList(response, 'data', []);
|
|
789
|
+
const tickers = {};
|
|
790
|
+
for (let i = 0; i < data.length; i++) {
|
|
791
|
+
const marketData = data[i];
|
|
792
|
+
const marketId = this.safeString(marketData, 'name');
|
|
793
|
+
const market = this.safeMarket(marketId);
|
|
794
|
+
const stats = this.safeDict(marketData, 'marketStats', {});
|
|
795
|
+
const ticker = this.parseTicker(stats, market);
|
|
796
|
+
const symbol = ticker['symbol'];
|
|
797
|
+
tickers[symbol] = ticker;
|
|
798
|
+
}
|
|
799
|
+
return this.filterByArrayTickers(tickers, 'symbol', symbols);
|
|
800
|
+
}
|
|
801
|
+
parseTicker(ticker, market = undefined) {
|
|
802
|
+
//
|
|
803
|
+
// {
|
|
804
|
+
// "dailyVolume": "231216165.666600",
|
|
805
|
+
// "dailyVolumeBase": "3027.36710",
|
|
806
|
+
// "dailyPriceChange": "181",
|
|
807
|
+
// "dailyPriceChangePercentage": "0.0024",
|
|
808
|
+
// "dailyLow": "75635",
|
|
809
|
+
// "dailyHigh": "77399",
|
|
810
|
+
// "lastPrice": "77026",
|
|
811
|
+
// "askPrice": "77026",
|
|
812
|
+
// "bidPrice": "77025",
|
|
813
|
+
// "markPrice": "77006.091897999984",
|
|
814
|
+
// "indexPrice": "77050.739529925005",
|
|
815
|
+
// "fundingRate": "0.000012",
|
|
816
|
+
// "nextFundingRate": 1777446000000,
|
|
817
|
+
// "openInterest": "114851569.088316",
|
|
818
|
+
// "openInterestBase": "1491.33012",
|
|
819
|
+
// "deleverageLevels": {
|
|
820
|
+
// "shortPositions": [
|
|
821
|
+
// { "level": 1, "rankingLowerBound": "-784.2884" },
|
|
822
|
+
// { "level": 2, "rankingLowerBound": "-2.1078" },
|
|
823
|
+
// { "level": 3, "rankingLowerBound": "-0.8754" },
|
|
824
|
+
// { "level": 4, "rankingLowerBound": "0.0000" }
|
|
825
|
+
// ],
|
|
826
|
+
// "longPositions": [
|
|
827
|
+
// { "level": 1, "rankingLowerBound": "-47747.2010" },
|
|
828
|
+
// { "level": 2, "rankingLowerBound": "-0.0131" },
|
|
829
|
+
// { "level": 3, "rankingLowerBound": "0.0019" },
|
|
830
|
+
// { "level": 4, "rankingLowerBound": "0.0032" }
|
|
831
|
+
// ]
|
|
832
|
+
// }
|
|
833
|
+
// }
|
|
834
|
+
//
|
|
835
|
+
const symbol = this.safeSymbol(undefined, market);
|
|
836
|
+
const last = this.safeNumber(ticker, 'lastPrice');
|
|
837
|
+
const percentageRaw = this.safeString(ticker, 'dailyPriceChangePercentage');
|
|
838
|
+
const percentage = (percentageRaw !== undefined) ? Precise["default"].stringMul(percentageRaw, '100') : undefined;
|
|
839
|
+
return this.safeTicker({
|
|
840
|
+
'symbol': symbol,
|
|
841
|
+
'timestamp': undefined,
|
|
842
|
+
'datetime': undefined,
|
|
843
|
+
'high': this.safeNumber(ticker, 'dailyHigh'),
|
|
844
|
+
'low': this.safeNumber(ticker, 'dailyLow'),
|
|
845
|
+
'bid': this.safeNumber(ticker, 'bidPrice'),
|
|
846
|
+
'bidVolume': undefined,
|
|
847
|
+
'ask': this.safeNumber(ticker, 'askPrice'),
|
|
848
|
+
'askVolume': undefined,
|
|
849
|
+
'vwap': undefined,
|
|
850
|
+
'open': undefined,
|
|
851
|
+
'close': last,
|
|
852
|
+
'last': last,
|
|
853
|
+
'previousClose': undefined,
|
|
854
|
+
'change': this.safeNumber(ticker, 'dailyPriceChange'),
|
|
855
|
+
'percentage': percentage,
|
|
856
|
+
'average': undefined,
|
|
857
|
+
'baseVolume': this.safeNumber(ticker, 'dailyVolumeBase'),
|
|
858
|
+
'quoteVolume': this.safeNumber(ticker, 'dailyVolume'),
|
|
859
|
+
'markPrice': this.safeNumber(ticker, 'markPrice'),
|
|
860
|
+
'indexPrice': this.safeNumber(ticker, 'indexPrice'),
|
|
861
|
+
'info': ticker,
|
|
862
|
+
}, market);
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* @method
|
|
866
|
+
* @name extended#fetchOrderBook
|
|
867
|
+
* @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
|
|
868
|
+
* @see https://api.docs.extended.exchange/#get-market-order-book
|
|
869
|
+
* @param {string} symbol unified symbol of the market to fetch the order book for
|
|
870
|
+
* @param {int} [limit] the maximum amount of order book entries to return
|
|
871
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
872
|
+
* @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
|
|
873
|
+
*/
|
|
874
|
+
async fetchOrderBook(symbol, limit = undefined, params = {}) {
|
|
875
|
+
await this.loadMarkets();
|
|
876
|
+
const market = this.market(symbol);
|
|
877
|
+
const request = {
|
|
878
|
+
'market': market['id'],
|
|
879
|
+
};
|
|
880
|
+
const response = await this.v1PublicGetInfoMarketsMarketOrderbook(this.extend(request, params));
|
|
881
|
+
//
|
|
882
|
+
// {
|
|
883
|
+
// "status": "OK",
|
|
884
|
+
// "data": {
|
|
885
|
+
// "market": "BTC-USD",
|
|
886
|
+
// "bid": [
|
|
887
|
+
// {
|
|
888
|
+
// "qty": "14.46084",
|
|
889
|
+
// "price": "76214"
|
|
890
|
+
// }
|
|
891
|
+
// ],
|
|
892
|
+
// "ask": [
|
|
893
|
+
// {
|
|
894
|
+
// "qty": "0.11585",
|
|
895
|
+
// "price": "76215"
|
|
896
|
+
// }
|
|
897
|
+
// ]
|
|
898
|
+
// }
|
|
899
|
+
// }
|
|
900
|
+
//
|
|
901
|
+
const data = this.safeDict(response, 'data', {});
|
|
902
|
+
const timestamp = this.milliseconds();
|
|
903
|
+
const orderbook = this.parseOrderBook(data, market['symbol'], timestamp, 'bid', 'ask', 'price', 'qty');
|
|
904
|
+
if (limit !== undefined) {
|
|
905
|
+
orderbook['bids'] = this.arraySlice(orderbook['bids'], 0, limit);
|
|
906
|
+
orderbook['asks'] = this.arraySlice(orderbook['asks'], 0, limit);
|
|
907
|
+
}
|
|
908
|
+
return orderbook;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* @method
|
|
912
|
+
* @name extended#fetchTrades
|
|
913
|
+
* @description get the list of most recent trades for a particular symbol
|
|
914
|
+
* @see https://api.docs.extended.exchange/#get-market-last-trades
|
|
915
|
+
* @param {string} symbol unified symbol of the market to fetch trades for
|
|
916
|
+
* @param {int} [since] timestamp in ms of the earliest trade to fetch
|
|
917
|
+
* @param {int} [limit] the maximum amount of trades to fetch
|
|
918
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
919
|
+
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
|
|
920
|
+
*/
|
|
921
|
+
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
|
|
922
|
+
await this.loadMarkets();
|
|
923
|
+
const market = this.market(symbol);
|
|
924
|
+
const request = {
|
|
925
|
+
'market': market['id'],
|
|
926
|
+
};
|
|
927
|
+
const response = await this.v1PublicGetInfoMarketsMarketTrades(this.extend(request, params));
|
|
928
|
+
//
|
|
929
|
+
// {
|
|
930
|
+
// "status": "OK",
|
|
931
|
+
// "data": [
|
|
932
|
+
// {
|
|
933
|
+
// "i": 2.049676905958871e+18,
|
|
934
|
+
// "m": "BTC-USD",
|
|
935
|
+
// "S": "SELL",
|
|
936
|
+
// "tT": "TRADE",
|
|
937
|
+
// "T": 1777516030193,
|
|
938
|
+
// "p": "76140",
|
|
939
|
+
// "q": "0.00165"
|
|
940
|
+
// }
|
|
941
|
+
// ]
|
|
942
|
+
// }
|
|
943
|
+
//
|
|
944
|
+
const data = this.safeList(response, 'data', []);
|
|
945
|
+
return this.parseTrades(data, market, since, limit);
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* @method
|
|
949
|
+
* @name extended#fetchMyTrades
|
|
950
|
+
* @description fetch all trades made by the user
|
|
951
|
+
* @see https://api.docs.extended.exchange/#get-trades
|
|
952
|
+
* @param {string} [symbol] unified market symbol of the trades
|
|
953
|
+
* @param {int} [since] the earliest time in ms to fetch trades for
|
|
954
|
+
* @param {int} [limit] the maximum number of trade structures to retrieve
|
|
955
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
956
|
+
* @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)
|
|
957
|
+
* @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
|
|
958
|
+
*/
|
|
959
|
+
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
960
|
+
await this.loadMarkets();
|
|
961
|
+
let paginate = false;
|
|
962
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchMyTrades', 'paginate');
|
|
963
|
+
if (paginate) {
|
|
964
|
+
return await this.fetchPaginatedCallCursor('fetchMyTrades', symbol, since, limit, params, 'cursor', 'cursor', undefined, 100);
|
|
965
|
+
}
|
|
966
|
+
let market = undefined;
|
|
967
|
+
const request = {};
|
|
968
|
+
if (symbol !== undefined) {
|
|
969
|
+
market = this.market(symbol);
|
|
970
|
+
request['market'] = market['id'];
|
|
971
|
+
}
|
|
972
|
+
if (limit !== undefined) {
|
|
973
|
+
request['limit'] = limit;
|
|
974
|
+
}
|
|
975
|
+
const response = await this.v1PrivateGetUserTrades(this.extend(params, request));
|
|
976
|
+
//
|
|
977
|
+
// {
|
|
978
|
+
// "status": "OK",
|
|
979
|
+
// "data": [
|
|
980
|
+
// {
|
|
981
|
+
// "id": 1,
|
|
982
|
+
// "orderId": 1784980437895231232,
|
|
983
|
+
// "externalId": "ExtId-1",
|
|
984
|
+
// "accountId": 1,
|
|
985
|
+
// "market": "BTC-USD",
|
|
986
|
+
// "side": "BUY",
|
|
987
|
+
// "price": "39000",
|
|
988
|
+
// "qty": "0.2",
|
|
989
|
+
// "value": "7800",
|
|
990
|
+
// "fee": "1.3",
|
|
991
|
+
// "tradeType": "TRADE",
|
|
992
|
+
// "isTaker": true,
|
|
993
|
+
// "createdTime": 1701563440000
|
|
994
|
+
// }
|
|
995
|
+
// ],
|
|
996
|
+
// "pagination": {
|
|
997
|
+
// "cursor": 1784963886257016832,
|
|
998
|
+
// "count": 1
|
|
999
|
+
// }
|
|
1000
|
+
// }
|
|
1001
|
+
//
|
|
1002
|
+
const data = this.safeList(response, 'data', []);
|
|
1003
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
1004
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
1005
|
+
const result = [];
|
|
1006
|
+
const dataLength = data.length;
|
|
1007
|
+
for (let i = 0; i < dataLength; i++) {
|
|
1008
|
+
let entry = data[i];
|
|
1009
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
1010
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
1011
|
+
}
|
|
1012
|
+
result.push(entry);
|
|
1013
|
+
}
|
|
1014
|
+
return this.parseTrades(result, market, since, limit);
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* @method
|
|
1018
|
+
* @name extended#fetchFundingHistory
|
|
1019
|
+
* @description fetch the funding payments history
|
|
1020
|
+
* @see https://api.docs.extended.exchange/#get-funding-payments
|
|
1021
|
+
* @param {string} [symbol] unified market symbol
|
|
1022
|
+
* @param {int} [since] the earliest time in ms to fetch funding history for
|
|
1023
|
+
* @param {int} [limit] the maximum number of funding history structures to retrieve
|
|
1024
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1025
|
+
* @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)
|
|
1026
|
+
* @returns {FundingHistory[]} a list of [funding history structures]{@link https://docs.ccxt.com/#/?id=funding-history-structure}
|
|
1027
|
+
*/
|
|
1028
|
+
async fetchFundingHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1029
|
+
await this.loadMarkets();
|
|
1030
|
+
let paginate = false;
|
|
1031
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchFundingHistory', 'paginate');
|
|
1032
|
+
if (paginate) {
|
|
1033
|
+
return await this.fetchPaginatedCallCursor('fetchFundingHistory', symbol, since, limit, params, 'cursor', 'cursor', undefined, 100);
|
|
1034
|
+
}
|
|
1035
|
+
let market = undefined;
|
|
1036
|
+
const request = {};
|
|
1037
|
+
if (symbol !== undefined) {
|
|
1038
|
+
market = this.market(symbol);
|
|
1039
|
+
request['market'] = market['id'];
|
|
1040
|
+
}
|
|
1041
|
+
if (since !== undefined) {
|
|
1042
|
+
request['startTime'] = since;
|
|
1043
|
+
}
|
|
1044
|
+
if (limit !== undefined) {
|
|
1045
|
+
request['limit'] = limit;
|
|
1046
|
+
}
|
|
1047
|
+
const response = await this.v1PrivateGetUserFundingHistory(this.extend(params, request));
|
|
1048
|
+
//
|
|
1049
|
+
// {
|
|
1050
|
+
// "status": "OK",
|
|
1051
|
+
// "data": [
|
|
1052
|
+
// {
|
|
1053
|
+
// "id": 8341,
|
|
1054
|
+
// "accountId": 3137,
|
|
1055
|
+
// "market": "BNB-USD",
|
|
1056
|
+
// "positionId": 1821237954501148672,
|
|
1057
|
+
// "side": "LONG",
|
|
1058
|
+
// "size": "1.116",
|
|
1059
|
+
// "value": "560.77401888",
|
|
1060
|
+
// "markPrice": "502.48568",
|
|
1061
|
+
// "fundingFee": "0",
|
|
1062
|
+
// "fundingRate": "0",
|
|
1063
|
+
// "paidTime": 1723147241346
|
|
1064
|
+
// }
|
|
1065
|
+
// ],
|
|
1066
|
+
// "pagination": {
|
|
1067
|
+
// "cursor": 8341,
|
|
1068
|
+
// "count": 1
|
|
1069
|
+
// }
|
|
1070
|
+
// }
|
|
1071
|
+
//
|
|
1072
|
+
const data = this.safeList(response, 'data', []);
|
|
1073
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
1074
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
1075
|
+
const result = [];
|
|
1076
|
+
const dataLength = data.length;
|
|
1077
|
+
for (let i = 0; i < dataLength; i++) {
|
|
1078
|
+
let entry = data[i];
|
|
1079
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
1080
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
1081
|
+
}
|
|
1082
|
+
result.push(entry);
|
|
1083
|
+
}
|
|
1084
|
+
return this.parseFundingHistories(result, market, since, limit);
|
|
1085
|
+
}
|
|
1086
|
+
parseFundingHistory(history, market = undefined) {
|
|
1087
|
+
//
|
|
1088
|
+
// {
|
|
1089
|
+
// "id": 8341,
|
|
1090
|
+
// "accountId": 3137,
|
|
1091
|
+
// "market": "BNB-USD",
|
|
1092
|
+
// "positionId": 1821237954501148672,
|
|
1093
|
+
// "side": "LONG",
|
|
1094
|
+
// "size": "1.116",
|
|
1095
|
+
// "value": "560.77401888",
|
|
1096
|
+
// "markPrice": "502.48568",
|
|
1097
|
+
// "fundingFee": "0",
|
|
1098
|
+
// "fundingRate": "0",
|
|
1099
|
+
// "paidTime": 1723147241346
|
|
1100
|
+
// }
|
|
1101
|
+
//
|
|
1102
|
+
const marketId = this.safeString(history, 'market');
|
|
1103
|
+
market = this.safeMarket(marketId, market);
|
|
1104
|
+
const timestamp = this.safeInteger(history, 'paidTime');
|
|
1105
|
+
return {
|
|
1106
|
+
'info': history,
|
|
1107
|
+
'symbol': market['symbol'],
|
|
1108
|
+
'code': market['settle'],
|
|
1109
|
+
'timestamp': timestamp,
|
|
1110
|
+
'datetime': this.iso8601(timestamp),
|
|
1111
|
+
'id': this.safeString(history, 'id'),
|
|
1112
|
+
'amount': this.safeNumber(history, 'fundingFee'),
|
|
1113
|
+
'rate': this.safeNumber(history, 'fundingRate'),
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
parseFundingHistories(histories, market = undefined, since = undefined, limit = undefined) {
|
|
1117
|
+
const result = [];
|
|
1118
|
+
for (let i = 0; i < histories.length; i++) {
|
|
1119
|
+
result.push(this.parseFundingHistory(histories[i], market));
|
|
1120
|
+
}
|
|
1121
|
+
const symbol = (market === undefined) ? undefined : market['symbol'];
|
|
1122
|
+
return this.filterBySymbolSinceLimit(result, symbol, since, limit);
|
|
1123
|
+
}
|
|
1124
|
+
parseTrade(trade, market = undefined) {
|
|
1125
|
+
//
|
|
1126
|
+
// fetchTrades
|
|
1127
|
+
//
|
|
1128
|
+
// {
|
|
1129
|
+
// "i": 2.049676905958871e+18,
|
|
1130
|
+
// "m": "BTC-USD",
|
|
1131
|
+
// "S": "SELL",
|
|
1132
|
+
// "tT": "TRADE",
|
|
1133
|
+
// "T": 1777516030193,
|
|
1134
|
+
// "p": "76140",
|
|
1135
|
+
// "q": "0.00165"
|
|
1136
|
+
// }
|
|
1137
|
+
//
|
|
1138
|
+
// fetchMyTrades
|
|
1139
|
+
//
|
|
1140
|
+
// {
|
|
1141
|
+
// "id": 1,
|
|
1142
|
+
// "orderId": 1784980437895231232,
|
|
1143
|
+
// "externalId": "ExtId-1",
|
|
1144
|
+
// "accountId": 1,
|
|
1145
|
+
// "market": "BTC-USD",
|
|
1146
|
+
// "side": "BUY",
|
|
1147
|
+
// "price": "39000",
|
|
1148
|
+
// "qty": "0.2",
|
|
1149
|
+
// "value": "7800",
|
|
1150
|
+
// "fee": "1.3",
|
|
1151
|
+
// "tradeType": "TRADE",
|
|
1152
|
+
// "isTaker": true,
|
|
1153
|
+
// "createdTime": 1701563440000
|
|
1154
|
+
// }
|
|
1155
|
+
//
|
|
1156
|
+
const marketId = this.safeString2(trade, 'm', 'market');
|
|
1157
|
+
market = this.safeMarket(marketId, market);
|
|
1158
|
+
const timestamp = this.safeInteger2(trade, 'T', 'createdTime');
|
|
1159
|
+
const priceString = this.safeString2(trade, 'p', 'price');
|
|
1160
|
+
const amountString = this.safeString2(trade, 'q', 'qty');
|
|
1161
|
+
const sideRaw = this.safeString2(trade, 'S', 'side');
|
|
1162
|
+
const side = (sideRaw !== undefined) ? sideRaw.toLowerCase() : undefined;
|
|
1163
|
+
const feeCost = this.safeString(trade, 'fee');
|
|
1164
|
+
const fee = (feeCost === undefined) ? undefined : {
|
|
1165
|
+
'cost': feeCost,
|
|
1166
|
+
'currency': (market === undefined) ? undefined : market['settle'],
|
|
1167
|
+
};
|
|
1168
|
+
const isTaker = this.safeBool(trade, 'isTaker');
|
|
1169
|
+
let takerOrMaker = undefined;
|
|
1170
|
+
if (isTaker !== undefined) {
|
|
1171
|
+
takerOrMaker = isTaker ? 'taker' : 'maker';
|
|
1172
|
+
}
|
|
1173
|
+
return this.safeTrade({
|
|
1174
|
+
'id': this.safeString2(trade, 'i', 'id'),
|
|
1175
|
+
'info': trade,
|
|
1176
|
+
'timestamp': timestamp,
|
|
1177
|
+
'datetime': this.iso8601(timestamp),
|
|
1178
|
+
'symbol': market['symbol'],
|
|
1179
|
+
'order': this.safeString(trade, 'orderId'),
|
|
1180
|
+
'type': undefined,
|
|
1181
|
+
'side': side,
|
|
1182
|
+
'takerOrMaker': takerOrMaker,
|
|
1183
|
+
'price': priceString,
|
|
1184
|
+
'amount': amountString,
|
|
1185
|
+
'cost': this.safeString(trade, 'value'),
|
|
1186
|
+
'fee': fee,
|
|
1187
|
+
}, market);
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* @method
|
|
1191
|
+
* @name extended#fetchOHLCV
|
|
1192
|
+
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
1193
|
+
* @see https://api.docs.extended.exchange/#get-candles-history
|
|
1194
|
+
* @param {string} symbol unified symbol of the market to fetch OHLCV data for
|
|
1195
|
+
* @param {string} timeframe the length of time each candle represents
|
|
1196
|
+
* @param {int} [since] timestamp in ms of the earliest candle to fetch
|
|
1197
|
+
* @param {int} [limit] the maximum amount of candles to fetch, default 100
|
|
1198
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1199
|
+
* @param {string} [params.candleType] candle type: 'trades' (default), 'mark-prices', or 'index-prices'
|
|
1200
|
+
* @param {string} [params.price] *ignored if params.candleType is set* 'mark' or 'index' for mark price and index price candles
|
|
1201
|
+
* @param {int} [params.until] end timestamp in ms for the requested period
|
|
1202
|
+
* @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
|
|
1203
|
+
*/
|
|
1204
|
+
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
|
1205
|
+
await this.loadMarkets();
|
|
1206
|
+
const market = this.market(symbol);
|
|
1207
|
+
const price = this.safeString(params, 'price');
|
|
1208
|
+
let candleType = this.safeString(params, 'candleType');
|
|
1209
|
+
if (candleType === undefined) {
|
|
1210
|
+
if (price === 'mark') {
|
|
1211
|
+
candleType = 'mark-prices';
|
|
1212
|
+
}
|
|
1213
|
+
else if (price === 'index') {
|
|
1214
|
+
candleType = 'index-prices';
|
|
1215
|
+
}
|
|
1216
|
+
else {
|
|
1217
|
+
candleType = 'trades';
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
const until = this.safeInteger(params, 'until');
|
|
1221
|
+
params = this.omit(params, ['candleType', 'price', 'until']);
|
|
1222
|
+
const request = {
|
|
1223
|
+
'market': market['id'],
|
|
1224
|
+
'candleType': candleType,
|
|
1225
|
+
'interval': this.safeString(this.timeframes, timeframe, timeframe),
|
|
1226
|
+
'limit': (limit !== undefined) ? limit : 100,
|
|
1227
|
+
};
|
|
1228
|
+
if (until !== undefined) {
|
|
1229
|
+
request['endTime'] = until;
|
|
1230
|
+
}
|
|
1231
|
+
const response = await this.v1PublicGetInfoCandlesMarketCandleType(this.extend(request, params));
|
|
1232
|
+
//
|
|
1233
|
+
// {
|
|
1234
|
+
// "status": "OK",
|
|
1235
|
+
// "data": [
|
|
1236
|
+
// {
|
|
1237
|
+
// "o": "75657.5",
|
|
1238
|
+
// "l": "75657.5",
|
|
1239
|
+
// "h": "75657.5",
|
|
1240
|
+
// "c": "75657.5",
|
|
1241
|
+
// "v": "0",
|
|
1242
|
+
// "T": 1777517880000
|
|
1243
|
+
// }
|
|
1244
|
+
// ]
|
|
1245
|
+
// }
|
|
1246
|
+
//
|
|
1247
|
+
const data = this.safeList(response, 'data', []);
|
|
1248
|
+
return this.parseOHLCVs(data, market, timeframe, since, limit);
|
|
1249
|
+
}
|
|
1250
|
+
parseOHLCV(ohlcv, market = undefined) {
|
|
1251
|
+
//
|
|
1252
|
+
// {
|
|
1253
|
+
// "o": "75657.5",
|
|
1254
|
+
// "l": "75657.5",
|
|
1255
|
+
// "h": "75657.5",
|
|
1256
|
+
// "c": "75657.5",
|
|
1257
|
+
// "v": "0",
|
|
1258
|
+
// "T": 1777517880000
|
|
1259
|
+
// }
|
|
1260
|
+
//
|
|
1261
|
+
return [
|
|
1262
|
+
this.safeInteger(ohlcv, 'T'),
|
|
1263
|
+
this.safeNumber(ohlcv, 'o'),
|
|
1264
|
+
this.safeNumber(ohlcv, 'h'),
|
|
1265
|
+
this.safeNumber(ohlcv, 'l'),
|
|
1266
|
+
this.safeNumber(ohlcv, 'c'),
|
|
1267
|
+
this.safeNumber(ohlcv, 'v'),
|
|
1268
|
+
];
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* @method
|
|
1272
|
+
* @name extended#fetchFundingRateHistory
|
|
1273
|
+
* @description fetches historical funding rate prices
|
|
1274
|
+
* @see https://api.docs.extended.exchange/#get-funding-rates-history
|
|
1275
|
+
* @param {string} symbol unified symbol of the market to fetch funding rate history for
|
|
1276
|
+
* @param {int} [since] timestamp in ms of the earliest funding rate to fetch
|
|
1277
|
+
* @param {int} [limit] the maximum amount of entries to fetch
|
|
1278
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1279
|
+
* @param {int} [params.until] timestamp in ms of the latest funding rate to fetch
|
|
1280
|
+
* @param {int} [params.endTime] exchange-specific end timestamp in ms of the latest funding rate to fetch
|
|
1281
|
+
* @param {int} [params.cursor] offset of the result set
|
|
1282
|
+
* @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)
|
|
1283
|
+
* @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
|
|
1284
|
+
*/
|
|
1285
|
+
async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1286
|
+
if (symbol === undefined) {
|
|
1287
|
+
throw new errors.ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
|
|
1288
|
+
}
|
|
1289
|
+
await this.loadMarkets();
|
|
1290
|
+
let paginate = false;
|
|
1291
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchFundingRateHistory', 'paginate');
|
|
1292
|
+
if (paginate) {
|
|
1293
|
+
return await this.fetchPaginatedCallCursor('fetchFundingRateHistory', symbol, since, limit, params, 'cursor', 'cursor', undefined, 10000);
|
|
1294
|
+
}
|
|
1295
|
+
const market = this.market(symbol);
|
|
1296
|
+
symbol = market['symbol'];
|
|
1297
|
+
if (limit === undefined) {
|
|
1298
|
+
limit = 100;
|
|
1299
|
+
}
|
|
1300
|
+
const until = this.safeInteger(params, 'until', this.milliseconds());
|
|
1301
|
+
const endTime = this.safeInteger(params, 'endTime', until);
|
|
1302
|
+
params = this.omit(params, ['endTime', 'until']);
|
|
1303
|
+
if (since === undefined) {
|
|
1304
|
+
since = endTime - (limit * 60 * 60 * 1000);
|
|
1305
|
+
}
|
|
1306
|
+
const request = {
|
|
1307
|
+
'market': market['id'],
|
|
1308
|
+
'startTime': since,
|
|
1309
|
+
'endTime': endTime,
|
|
1310
|
+
'limit': limit,
|
|
1311
|
+
};
|
|
1312
|
+
const response = await this.v1PublicGetInfoMarketFunding(this.extend(request, params));
|
|
1313
|
+
//
|
|
1314
|
+
// {
|
|
1315
|
+
// "status": "OK",
|
|
1316
|
+
// "data": [
|
|
1317
|
+
// {
|
|
1318
|
+
// "m": "BTC-USD",
|
|
1319
|
+
// "f": "0.000008",
|
|
1320
|
+
// "T": 1777507201028
|
|
1321
|
+
// }
|
|
1322
|
+
// ],
|
|
1323
|
+
// "pagination": {
|
|
1324
|
+
// "cursor": 1784963886257016832,
|
|
1325
|
+
// "count": 1
|
|
1326
|
+
// }
|
|
1327
|
+
// }
|
|
1328
|
+
//
|
|
1329
|
+
const data = this.safeList(response, 'data', []);
|
|
1330
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
1331
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
1332
|
+
const result = [];
|
|
1333
|
+
const dataLength = data.length;
|
|
1334
|
+
for (let i = 0; i < dataLength; i++) {
|
|
1335
|
+
let entry = data[i];
|
|
1336
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
1337
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
1338
|
+
}
|
|
1339
|
+
result.push(this.parseFundingRateHistory(entry, market));
|
|
1340
|
+
}
|
|
1341
|
+
const sorted = this.sortBy(result, 'timestamp');
|
|
1342
|
+
return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
|
|
1343
|
+
}
|
|
1344
|
+
parseFundingRateHistory(info, market = undefined) {
|
|
1345
|
+
//
|
|
1346
|
+
// {
|
|
1347
|
+
// "m": "BTC-USD",
|
|
1348
|
+
// "f": "0.000008",
|
|
1349
|
+
// "T": 1777507201028
|
|
1350
|
+
// }
|
|
1351
|
+
//
|
|
1352
|
+
const marketId = this.safeString(info, 'm');
|
|
1353
|
+
market = this.safeMarket(marketId, market);
|
|
1354
|
+
const timestamp = this.safeInteger(info, 'T');
|
|
1355
|
+
return {
|
|
1356
|
+
'info': info,
|
|
1357
|
+
'symbol': market['symbol'],
|
|
1358
|
+
'fundingRate': this.safeNumber(info, 'f'),
|
|
1359
|
+
'timestamp': timestamp,
|
|
1360
|
+
'datetime': this.iso8601(timestamp),
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* @method
|
|
1365
|
+
* @name extended#fetchOpenInterestHistory
|
|
1366
|
+
* @description Retrieves the open interest history of a currency
|
|
1367
|
+
* @see https://api.docs.extended.exchange/#get-open-interest-history
|
|
1368
|
+
* @param {string} symbol unified CCXT market symbol
|
|
1369
|
+
* @param {string} timeframe '1h' or '1d'
|
|
1370
|
+
* @param {int} [since] the time(ms) of the earliest record to retrieve as a unix timestamp
|
|
1371
|
+
* @param {int} [limit] the maximum amount of open interest structures to retrieve
|
|
1372
|
+
* @param {object} [params] exchange specific parameters
|
|
1373
|
+
* @param {int} [params.until] timestamp in ms of the latest open interest record to fetch
|
|
1374
|
+
* @returns {object[]} an array of [open interest structures]{@link https://docs.ccxt.com/#/?id=open-interest-structure}
|
|
1375
|
+
*/
|
|
1376
|
+
async fetchOpenInterestHistory(symbol, timeframe = '1h', since = undefined, limit = undefined, params = {}) {
|
|
1377
|
+
await this.loadMarkets();
|
|
1378
|
+
const market = this.market(symbol);
|
|
1379
|
+
const interval = this.safeString(this.timeframes, timeframe);
|
|
1380
|
+
if (!this.inArray(interval, ['PT1H', 'P1D'])) {
|
|
1381
|
+
throw new errors.BadRequest(this.id + ' fetchOpenInterestHistory() supports 1h and 1d timeframes only');
|
|
1382
|
+
}
|
|
1383
|
+
if (limit === undefined) {
|
|
1384
|
+
limit = 100;
|
|
1385
|
+
}
|
|
1386
|
+
const until = this.safeInteger(params, 'until', this.milliseconds());
|
|
1387
|
+
const endTime = this.safeInteger(params, 'endTime', until);
|
|
1388
|
+
params = this.omit(params, ['endTime', 'until']);
|
|
1389
|
+
if (since === undefined) {
|
|
1390
|
+
since = endTime - (limit * this.parseTimeframe(timeframe) * 1000);
|
|
1391
|
+
}
|
|
1392
|
+
const request = {
|
|
1393
|
+
'market': market['id'],
|
|
1394
|
+
'interval': interval,
|
|
1395
|
+
'startTime': since,
|
|
1396
|
+
'endTime': endTime,
|
|
1397
|
+
'limit': limit,
|
|
1398
|
+
};
|
|
1399
|
+
const response = await this.v1PublicGetInfoMarketOpenInterests(this.extend(request, params));
|
|
1400
|
+
//
|
|
1401
|
+
// {
|
|
1402
|
+
// "status": "OK",
|
|
1403
|
+
// "data": [
|
|
1404
|
+
// {
|
|
1405
|
+
// "i": "112620590.6060360000000000",
|
|
1406
|
+
// "I": "1473.1408400000000000",
|
|
1407
|
+
// "t": 1777420800000
|
|
1408
|
+
// }
|
|
1409
|
+
// ]
|
|
1410
|
+
// }
|
|
1411
|
+
//
|
|
1412
|
+
const data = this.safeList(response, 'data', []);
|
|
1413
|
+
return this.parseOpenInterestsHistory(data, market, since, limit);
|
|
1414
|
+
}
|
|
1415
|
+
parseOpenInterest(interest, market = undefined) {
|
|
1416
|
+
//
|
|
1417
|
+
// {
|
|
1418
|
+
// "i": "112620590.6060360000000000",
|
|
1419
|
+
// "I": "1473.1408400000000000",
|
|
1420
|
+
// "t": 1777420800000
|
|
1421
|
+
// }
|
|
1422
|
+
//
|
|
1423
|
+
const timestamp = this.safeInteger(interest, 't');
|
|
1424
|
+
return this.safeOpenInterest({
|
|
1425
|
+
'symbol': market['symbol'],
|
|
1426
|
+
'openInterestAmount': this.safeNumber(interest, 'I'),
|
|
1427
|
+
'openInterestValue': this.safeNumber(interest, 'i'),
|
|
1428
|
+
'baseVolume': this.safeNumber(interest, 'I'),
|
|
1429
|
+
'quoteVolume': this.safeNumber(interest, 'i'),
|
|
1430
|
+
'timestamp': timestamp,
|
|
1431
|
+
'datetime': this.iso8601(timestamp),
|
|
1432
|
+
'info': interest,
|
|
1433
|
+
}, market);
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* @method
|
|
1437
|
+
* @name extended#fetchBalance
|
|
1438
|
+
* @description query for balance and get the amount of funds available for trading or funds locked in orders
|
|
1439
|
+
* @see https://api.docs.extended.exchange/#get-spot-balances
|
|
1440
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1441
|
+
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/?id=balance-structure}
|
|
1442
|
+
*/
|
|
1443
|
+
async fetchBalance(params = {}) {
|
|
1444
|
+
await this.loadMarkets();
|
|
1445
|
+
const response = await this.v1PrivateGetUserSpotBalances(params);
|
|
1446
|
+
//
|
|
1447
|
+
// {
|
|
1448
|
+
// "status": "OK",
|
|
1449
|
+
// "data": [
|
|
1450
|
+
// {
|
|
1451
|
+
// "accountId": 123,
|
|
1452
|
+
// "asset": "USDC",
|
|
1453
|
+
// "balance": "13500",
|
|
1454
|
+
// "indexPrice": "1",
|
|
1455
|
+
// "notionalValue": "13500",
|
|
1456
|
+
// "contributionFactor": "1",
|
|
1457
|
+
// "equityContribution": "13500",
|
|
1458
|
+
// "availableToWithdraw": "100",
|
|
1459
|
+
// "updatedAt": 1701563440
|
|
1460
|
+
// },
|
|
1461
|
+
// {
|
|
1462
|
+
// "accountId": 123,
|
|
1463
|
+
// "asset": "BTC",
|
|
1464
|
+
// "balance": "0.5",
|
|
1465
|
+
// "indexPrice": "65000",
|
|
1466
|
+
// "notionalValue": "32500",
|
|
1467
|
+
// "contributionFactor": "0.95",
|
|
1468
|
+
// "equityContribution": "30875",
|
|
1469
|
+
// "availableToWithdraw": "0.5",
|
|
1470
|
+
// "updatedAt": 1701563440
|
|
1471
|
+
// }
|
|
1472
|
+
// ]
|
|
1473
|
+
// }
|
|
1474
|
+
//
|
|
1475
|
+
const data = this.safeList(response, 'data', []);
|
|
1476
|
+
return this.parseBalance(data);
|
|
1477
|
+
}
|
|
1478
|
+
parseBalance(response) {
|
|
1479
|
+
const result = { 'info': response };
|
|
1480
|
+
for (let i = 0; i < response.length; i++) {
|
|
1481
|
+
const balance = this.safeDict(response, i, {});
|
|
1482
|
+
const currencyId = this.safeString(balance, 'asset');
|
|
1483
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
1484
|
+
const account = this.account();
|
|
1485
|
+
account['free'] = this.safeString(balance, 'availableToWithdraw');
|
|
1486
|
+
account['total'] = this.safeString(balance, 'balance');
|
|
1487
|
+
result[code] = account;
|
|
1488
|
+
}
|
|
1489
|
+
return this.safeBalance(result);
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* @method
|
|
1493
|
+
* @name extended#fetchAccount
|
|
1494
|
+
* @description fetch the current authenticated sub-account
|
|
1495
|
+
* @see https://api.docs.extended.exchange/#get-account-details
|
|
1496
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1497
|
+
* @returns {object} an [account structure]{@link https://docs.ccxt.com/#/?id=account-structure}
|
|
1498
|
+
*/
|
|
1499
|
+
async fetchAccount(params = {}) {
|
|
1500
|
+
const response = await this.v1PrivateGetUserAccountInfo(params);
|
|
1501
|
+
//
|
|
1502
|
+
// {
|
|
1503
|
+
// "status": "OK",
|
|
1504
|
+
// "data": {
|
|
1505
|
+
// "accountId": 3342,
|
|
1506
|
+
// "description": "Main account",
|
|
1507
|
+
// "accountIndex": 0,
|
|
1508
|
+
// "status": "ACTIVE",
|
|
1509
|
+
// "l2Key": "0x...",
|
|
1510
|
+
// "l2Vault": "500343",
|
|
1511
|
+
// "bridgeStarknetAddress": "0x...",
|
|
1512
|
+
// "apiKeys": [
|
|
1513
|
+
// "..."
|
|
1514
|
+
// ],
|
|
1515
|
+
// "accountIndexForKeyGeneration": 0
|
|
1516
|
+
// }
|
|
1517
|
+
// }
|
|
1518
|
+
//
|
|
1519
|
+
const data = this.safeDict(response, 'data', {});
|
|
1520
|
+
return this.parseAccount(data);
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* @method
|
|
1524
|
+
* @name extended#fetchAccounts
|
|
1525
|
+
* @description fetch the current authenticated sub-account, extended private endpoints only return records for the authenticated sub-account
|
|
1526
|
+
* @see https://api.docs.extended.exchange/#get-sub-accounts
|
|
1527
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1528
|
+
* @returns {object[]} a list of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure}
|
|
1529
|
+
*/
|
|
1530
|
+
async fetchAccounts(params = {}) {
|
|
1531
|
+
const response = await this.v1PrivateGetUserAccounts(params);
|
|
1532
|
+
//
|
|
1533
|
+
// {
|
|
1534
|
+
// "status": "OK",
|
|
1535
|
+
// "data": [{
|
|
1536
|
+
// "accountId": 123,
|
|
1537
|
+
// "description": "Main",
|
|
1538
|
+
// "accountIndex": 0,
|
|
1539
|
+
// "status": "ACTIVE",
|
|
1540
|
+
// "l2Key": "0x123",
|
|
1541
|
+
// "l2Vault": "321",
|
|
1542
|
+
// "bridgeStarknetAddress": "0xabc",
|
|
1543
|
+
// "accountIndexForKeyGeneration": 0
|
|
1544
|
+
// }, {
|
|
1545
|
+
// "accountId": 999,
|
|
1546
|
+
// "description": "Vault Balance",
|
|
1547
|
+
// "accountIndex": 1001,
|
|
1548
|
+
// "status": "ACTIVE",
|
|
1549
|
+
// "l2Key": "0x123",
|
|
1550
|
+
// "l2Vault": "999",
|
|
1551
|
+
// "bridgeStarknetAddress": "0xabc",
|
|
1552
|
+
// "accountIndexForKeyGeneration": 0
|
|
1553
|
+
// }
|
|
1554
|
+
// ]}
|
|
1555
|
+
//
|
|
1556
|
+
const data = this.safeList(response, 'data', []);
|
|
1557
|
+
return this.parseAccounts(data);
|
|
1558
|
+
}
|
|
1559
|
+
parseAccount(account) {
|
|
1560
|
+
const accountIndex = this.safeInteger(account, 'accountIndex');
|
|
1561
|
+
let type = undefined;
|
|
1562
|
+
if (accountIndex !== undefined) {
|
|
1563
|
+
type = (accountIndex === 0) ? 'main' : 'subaccount';
|
|
1564
|
+
}
|
|
1565
|
+
return {
|
|
1566
|
+
'id': this.safeString2(account, 'accountId', 'id'),
|
|
1567
|
+
'type': type,
|
|
1568
|
+
'code': undefined,
|
|
1569
|
+
'info': account,
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
/**
|
|
1573
|
+
* @method
|
|
1574
|
+
* @name extended#fetchLedger
|
|
1575
|
+
* @description fetch the history of changes, actions done by the user or operations that altered the balance of the user
|
|
1576
|
+
* @see https://api.docs.extended.exchange/#get-deposits-withdrawals-transfers-history
|
|
1577
|
+
* @param {string} [code] unified currency code
|
|
1578
|
+
* @param {int} [since] timestamp in ms of the earliest ledger entry
|
|
1579
|
+
* @param {int} [limit] max number of ledger entries to return
|
|
1580
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1581
|
+
* @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)
|
|
1582
|
+
* @returns {object[]} a list of [ledger structures]{@link https://docs.ccxt.com/#/?id=ledger}
|
|
1583
|
+
*/
|
|
1584
|
+
async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1585
|
+
await this.loadMarkets();
|
|
1586
|
+
let paginate = false;
|
|
1587
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchLedger', 'paginate');
|
|
1588
|
+
if (paginate) {
|
|
1589
|
+
return await this.fetchPaginatedCallCursor('fetchLedger', code, since, limit, params, 'cursor', 'cursor', undefined, 50);
|
|
1590
|
+
}
|
|
1591
|
+
let currency = undefined;
|
|
1592
|
+
if (code !== undefined) {
|
|
1593
|
+
currency = this.currency(code);
|
|
1594
|
+
}
|
|
1595
|
+
const request = {};
|
|
1596
|
+
if (limit !== undefined) {
|
|
1597
|
+
request['limit'] = limit;
|
|
1598
|
+
}
|
|
1599
|
+
const response = await this.v1PrivateGetUserAssetOperations(this.extend(request, params));
|
|
1600
|
+
const data = this.safeList(response, 'data', []);
|
|
1601
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
1602
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
1603
|
+
const result = [];
|
|
1604
|
+
const dataLength = data.length;
|
|
1605
|
+
for (let i = 0; i < dataLength; i++) {
|
|
1606
|
+
let entry = data[i];
|
|
1607
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
1608
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
1609
|
+
}
|
|
1610
|
+
result.push(entry);
|
|
1611
|
+
}
|
|
1612
|
+
return this.parseLedger(result, currency, since, limit);
|
|
1613
|
+
}
|
|
1614
|
+
parseLedgerEntry(item, currency = undefined) {
|
|
1615
|
+
//
|
|
1616
|
+
// {
|
|
1617
|
+
// "id": "1951255127004282880",
|
|
1618
|
+
// "type": "TRANSFER",
|
|
1619
|
+
// "status": "COMPLETED",
|
|
1620
|
+
// "amount": "-3.0000000000000000",
|
|
1621
|
+
// "fee": "0",
|
|
1622
|
+
// "asset": 1,
|
|
1623
|
+
// "time": 1754050449502,
|
|
1624
|
+
// "accountId": 100009,
|
|
1625
|
+
// "counterpartyAccountId": 100023
|
|
1626
|
+
// }
|
|
1627
|
+
//
|
|
1628
|
+
const timestamp = this.safeInteger(item, 'time');
|
|
1629
|
+
const assetId = this.safeString(item, 'asset');
|
|
1630
|
+
const code = this.getExtendedCurrencyCodeById(assetId, currency);
|
|
1631
|
+
const ledgerCurrency = this.safeCurrency(code, currency);
|
|
1632
|
+
const amountString = this.safeString(item, 'amount');
|
|
1633
|
+
let direction = undefined;
|
|
1634
|
+
if (amountString !== undefined) {
|
|
1635
|
+
direction = Precise["default"].stringLt(amountString, '0') ? 'out' : 'in';
|
|
1636
|
+
}
|
|
1637
|
+
let fee = undefined;
|
|
1638
|
+
const feeCost = this.safeString(item, 'fee');
|
|
1639
|
+
if (feeCost !== undefined) {
|
|
1640
|
+
fee = {
|
|
1641
|
+
'currency': code,
|
|
1642
|
+
'cost': this.parseNumber(Precise["default"].stringAbs(feeCost)),
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
return this.safeLedgerEntry({
|
|
1646
|
+
'info': item,
|
|
1647
|
+
'id': this.safeString(item, 'id'),
|
|
1648
|
+
'timestamp': timestamp,
|
|
1649
|
+
'datetime': this.iso8601(timestamp),
|
|
1650
|
+
'direction': direction,
|
|
1651
|
+
'account': this.safeString(item, 'accountId'),
|
|
1652
|
+
'referenceId': this.safeString(item, 'transactionHash'),
|
|
1653
|
+
'referenceAccount': this.safeString(item, 'counterpartyAccountId'),
|
|
1654
|
+
'type': this.parseTransactionType(this.safeString(item, 'type')),
|
|
1655
|
+
'currency': code,
|
|
1656
|
+
'amount': (amountString === undefined) ? undefined : this.parseNumber(Precise["default"].stringAbs(amountString)),
|
|
1657
|
+
'before': undefined,
|
|
1658
|
+
'after': undefined,
|
|
1659
|
+
'status': this.parseTransactionStatus(this.safeString(item, 'status')),
|
|
1660
|
+
'fee': fee,
|
|
1661
|
+
}, ledgerCurrency);
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* @method
|
|
1665
|
+
* @name extended#fetchTransactions
|
|
1666
|
+
* @description fetch history of deposits, withdrawals, and transfers
|
|
1667
|
+
* @see https://api.docs.extended.exchange/#get-deposits-withdrawals-transfers-history
|
|
1668
|
+
* @param {string} [code] unified currency code
|
|
1669
|
+
* @param {int} [since] the earliest time in ms to fetch transactions for
|
|
1670
|
+
* @param {int} [limit] the maximum number of transaction structures to retrieve
|
|
1671
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1672
|
+
* @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)
|
|
1673
|
+
* @returns {Transaction[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
1674
|
+
*/
|
|
1675
|
+
async fetchTransactions(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1676
|
+
await this.loadMarkets();
|
|
1677
|
+
let paginate = false;
|
|
1678
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchTransactions', 'paginate');
|
|
1679
|
+
if (paginate) {
|
|
1680
|
+
return await this.fetchPaginatedCallCursor('fetchTransactions', code, since, limit, params, 'cursor', 'cursor', undefined, 50);
|
|
1681
|
+
}
|
|
1682
|
+
let currency = undefined;
|
|
1683
|
+
if (code !== undefined) {
|
|
1684
|
+
currency = this.currency(code);
|
|
1685
|
+
}
|
|
1686
|
+
const request = {};
|
|
1687
|
+
if (limit !== undefined) {
|
|
1688
|
+
request['limit'] = limit;
|
|
1689
|
+
}
|
|
1690
|
+
const response = await this.v1PrivateGetUserAssetOperations(this.extend(request, params));
|
|
1691
|
+
//
|
|
1692
|
+
// {
|
|
1693
|
+
// "status": "OK",
|
|
1694
|
+
// "data": [
|
|
1695
|
+
// {
|
|
1696
|
+
// "id": "1951255127004282880",
|
|
1697
|
+
// "type": "TRANSFER",
|
|
1698
|
+
// "status": "COMPLETED",
|
|
1699
|
+
// "amount": "-3.0000000000000000",
|
|
1700
|
+
// "fee": "0",
|
|
1701
|
+
// "asset": 1,
|
|
1702
|
+
// "time": 1754050449502,
|
|
1703
|
+
// "accountId": 100009,
|
|
1704
|
+
// "counterpartyAccountId": 100023
|
|
1705
|
+
// }
|
|
1706
|
+
// ],
|
|
1707
|
+
// "pagination": {
|
|
1708
|
+
// "cursor": 1951255127004282880,
|
|
1709
|
+
// "count": 1
|
|
1710
|
+
// }
|
|
1711
|
+
// }
|
|
1712
|
+
//
|
|
1713
|
+
const data = this.safeList(response, 'data', []);
|
|
1714
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
1715
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
1716
|
+
const result = [];
|
|
1717
|
+
const dataLength = data.length;
|
|
1718
|
+
for (let i = 0; i < dataLength; i++) {
|
|
1719
|
+
let entry = data[i];
|
|
1720
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
1721
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
1722
|
+
}
|
|
1723
|
+
result.push(entry);
|
|
1724
|
+
}
|
|
1725
|
+
return this.parseTransactions(result, currency, since, limit);
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* @method
|
|
1729
|
+
* @name extended#fetchDeposits
|
|
1730
|
+
* @description fetch all deposits made to an account
|
|
1731
|
+
* @see https://api.docs.extended.exchange/#get-deposits-withdrawals-transfers-history
|
|
1732
|
+
* @param {string} [code] unified currency code
|
|
1733
|
+
* @param {int} [since] the earliest time in ms to fetch deposits for
|
|
1734
|
+
* @param {int} [limit] the maximum number of deposit structures to retrieve
|
|
1735
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1736
|
+
* @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)
|
|
1737
|
+
* @returns {Transaction[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
1738
|
+
*/
|
|
1739
|
+
async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1740
|
+
return await this.fetchTransactions(code, since, limit, this.extend({ 'type': 'DEPOSIT' }, params));
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* @method
|
|
1744
|
+
* @name extended#fetchWithdrawals
|
|
1745
|
+
* @description fetch all withdrawals made from an account
|
|
1746
|
+
* @see https://api.docs.extended.exchange/#get-deposits-withdrawals-transfers-history
|
|
1747
|
+
* @param {string} [code] unified currency code
|
|
1748
|
+
* @param {int} [since] the earliest time in ms to fetch withdrawals for
|
|
1749
|
+
* @param {int} [limit] the maximum number of withdrawal structures to retrieve
|
|
1750
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1751
|
+
* @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)
|
|
1752
|
+
* @returns {Transaction[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
|
|
1753
|
+
*/
|
|
1754
|
+
async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1755
|
+
return await this.fetchTransactions(code, since, limit, this.extend({ 'type': 'WITHDRAWAL' }, params));
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* @method
|
|
1759
|
+
* @name extended#withdraw
|
|
1760
|
+
* @description make a Starknet withdrawal
|
|
1761
|
+
* @see https://api.docs.extended.exchange/#withdrawals
|
|
1762
|
+
* @param {string} code unified currency code
|
|
1763
|
+
* @param {float} amount the amount to withdraw
|
|
1764
|
+
* @param {string} address the Starknet address to withdraw to
|
|
1765
|
+
* @param {string} tag unused
|
|
1766
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1767
|
+
* @param {string} [params.chainId] only STRK is supported
|
|
1768
|
+
* @param {int} [params.settlementExpiration] settlement expiration timestamp in seconds, defaults to now + 14 days + 60 seconds
|
|
1769
|
+
* @returns {object} a [transaction structure]{@link https://docs.ccxt.com/?id=transaction-structure}
|
|
1770
|
+
*/
|
|
1771
|
+
async withdraw(code, amount, address, tag = undefined, params = {}) {
|
|
1772
|
+
this.checkRequiredCredentials();
|
|
1773
|
+
await this.loadMarkets();
|
|
1774
|
+
const currency = this.currency(code);
|
|
1775
|
+
const chainId = this.safeStringUpper2(params, 'chainId', 'network', 'STRK');
|
|
1776
|
+
if (chainId !== 'STRK') {
|
|
1777
|
+
throw new errors.BadRequest(this.id + ' withdraw() only supports Starknet withdrawals with chainId STRK');
|
|
1778
|
+
}
|
|
1779
|
+
if (address.length <= 42) {
|
|
1780
|
+
throw new errors.BadRequest(this.id + ' withdraw() requires a Starknet address for STRK withdrawals, EVM withdrawals require the bridge quote flow');
|
|
1781
|
+
}
|
|
1782
|
+
const account = await this.fetchExtendedAccount();
|
|
1783
|
+
const amountString = this.currencyToPrecision(code, amount);
|
|
1784
|
+
const accountId = this.safeString(account, 'accountId');
|
|
1785
|
+
const settlement = this.createWithdrawalSettlementData(address, amountString, currency, account, params);
|
|
1786
|
+
const request = {
|
|
1787
|
+
'accountId': accountId,
|
|
1788
|
+
'amount': amountString,
|
|
1789
|
+
'chainId': chainId,
|
|
1790
|
+
'asset': currency['id'],
|
|
1791
|
+
'settlement': settlement,
|
|
1792
|
+
};
|
|
1793
|
+
params = this.omit(params, ['chainId', 'network', 'settlementExpiration', 'nonce', 'recipient', 'positionId', 'l2Vault', 'collateralId', 'resolution']);
|
|
1794
|
+
const response = await this.v1PrivatePostUserWithdrawal(this.extend(request, params));
|
|
1795
|
+
//
|
|
1796
|
+
// {
|
|
1797
|
+
// "status": "OK",
|
|
1798
|
+
// "data": 1820796462590083072
|
|
1799
|
+
// }
|
|
1800
|
+
//
|
|
1801
|
+
const now = this.milliseconds();
|
|
1802
|
+
return {
|
|
1803
|
+
'info': response,
|
|
1804
|
+
'id': this.safeString(response, 'data'),
|
|
1805
|
+
'txid': undefined,
|
|
1806
|
+
'timestamp': now,
|
|
1807
|
+
'datetime': this.iso8601(now),
|
|
1808
|
+
'address': address,
|
|
1809
|
+
'addressFrom': undefined,
|
|
1810
|
+
'addressTo': address,
|
|
1811
|
+
'tag': tag,
|
|
1812
|
+
'tagFrom': undefined,
|
|
1813
|
+
'tagTo': tag,
|
|
1814
|
+
'type': 'withdrawal',
|
|
1815
|
+
'amount': this.parseNumber(amountString),
|
|
1816
|
+
'currency': currency['code'],
|
|
1817
|
+
'status': 'pending',
|
|
1818
|
+
'updated': now,
|
|
1819
|
+
'fee': undefined,
|
|
1820
|
+
'network': chainId,
|
|
1821
|
+
'comment': undefined,
|
|
1822
|
+
'internal': false,
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* @method
|
|
1827
|
+
* @name extended#fetchTransfers
|
|
1828
|
+
* @description fetch a history of internal transfers made on an account
|
|
1829
|
+
* @see https://api.docs.extended.exchange/#get-deposits-withdrawals-transfers-history
|
|
1830
|
+
* @param {string} [code] unified currency code
|
|
1831
|
+
* @param {int} [since] the earliest time in ms to fetch transfers for
|
|
1832
|
+
* @param {int} [limit] the maximum number of transfer structures to retrieve
|
|
1833
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1834
|
+
* @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)
|
|
1835
|
+
* @returns {TransferEntry[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
|
|
1836
|
+
*/
|
|
1837
|
+
async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
|
|
1838
|
+
await this.loadMarkets();
|
|
1839
|
+
let paginate = false;
|
|
1840
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchTransfers', 'paginate');
|
|
1841
|
+
if (paginate) {
|
|
1842
|
+
return await this.fetchPaginatedCallCursor('fetchTransfers', code, since, limit, params, 'cursor', 'cursor', undefined, 50);
|
|
1843
|
+
}
|
|
1844
|
+
let currency = undefined;
|
|
1845
|
+
if (code !== undefined) {
|
|
1846
|
+
currency = this.currency(code);
|
|
1847
|
+
}
|
|
1848
|
+
const request = {
|
|
1849
|
+
'type': 'TRANSFER',
|
|
1850
|
+
};
|
|
1851
|
+
if (limit !== undefined) {
|
|
1852
|
+
request['limit'] = limit;
|
|
1853
|
+
}
|
|
1854
|
+
const response = await this.v1PrivateGetUserAssetOperations(this.extend(request, params));
|
|
1855
|
+
const data = this.safeList(response, 'data', []);
|
|
1856
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
1857
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
1858
|
+
const result = [];
|
|
1859
|
+
const dataLength = data.length;
|
|
1860
|
+
for (let i = 0; i < dataLength; i++) {
|
|
1861
|
+
let entry = data[i];
|
|
1862
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
1863
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
1864
|
+
}
|
|
1865
|
+
result.push(entry);
|
|
1866
|
+
}
|
|
1867
|
+
return this.parseTransfers(result, currency, since, limit);
|
|
1868
|
+
}
|
|
1869
|
+
/**
|
|
1870
|
+
* @method
|
|
1871
|
+
* @name extended#transfer
|
|
1872
|
+
* @description transfer collateral between sub-accounts associated with the same wallet
|
|
1873
|
+
* @see https://api.docs.extended.exchange/#create-transfer
|
|
1874
|
+
* @param {string} code unified currency code
|
|
1875
|
+
* @param {float} amount the amount to transfer
|
|
1876
|
+
* @param {string} fromAccount source account id, defaults to the authenticated account id
|
|
1877
|
+
* @param {string} toAccount destination account id
|
|
1878
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
1879
|
+
* @param {string} params.toVault destination account L2 vault
|
|
1880
|
+
* @param {string} params.toL2Key destination account L2 public key
|
|
1881
|
+
* @param {int} [params.settlementExpiration] settlement expiration timestamp in seconds, defaults to now + 21 days
|
|
1882
|
+
* @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
|
|
1883
|
+
*/
|
|
1884
|
+
async transfer(code, amount, fromAccount, toAccount, params = {}) {
|
|
1885
|
+
this.checkRequiredCredentials();
|
|
1886
|
+
await this.loadMarkets();
|
|
1887
|
+
const currency = this.currency(code);
|
|
1888
|
+
const account = await this.fetchExtendedAccount();
|
|
1889
|
+
const currentAccountId = this.safeString(account, 'accountId');
|
|
1890
|
+
if (fromAccount === undefined) {
|
|
1891
|
+
fromAccount = currentAccountId;
|
|
1892
|
+
}
|
|
1893
|
+
else if (fromAccount !== currentAccountId) {
|
|
1894
|
+
throw new errors.BadRequest(this.id + ' transfer() can only transfer from the authenticated account');
|
|
1895
|
+
}
|
|
1896
|
+
const toVault = this.safeString2(params, 'toVault', 'receiverPositionId');
|
|
1897
|
+
const toL2Key = this.safeString2(params, 'toL2Key', 'receiverPublicKey');
|
|
1898
|
+
if ((toAccount === undefined) || (toVault === undefined) || (toL2Key === undefined)) {
|
|
1899
|
+
throw new errors.ArgumentsRequired(this.id + ' transfer() requires a toAccount argument and params["toVault"] and params["toL2Key"]');
|
|
1900
|
+
}
|
|
1901
|
+
const amountString = this.currencyToPrecision(code, amount);
|
|
1902
|
+
const settlement = this.createTransferSettlementData(amountString, currency, account, toVault, toL2Key, params);
|
|
1903
|
+
const request = {
|
|
1904
|
+
'fromAccount': fromAccount,
|
|
1905
|
+
'toAccount': toAccount,
|
|
1906
|
+
'amount': amountString,
|
|
1907
|
+
'transferredAsset': currency['id'],
|
|
1908
|
+
'settlement': settlement,
|
|
1909
|
+
};
|
|
1910
|
+
params = this.omit(params, ['fromVault', 'senderPositionId', 'fromL2Key', 'senderPublicKey', 'toVault', 'receiverPositionId', 'toL2Key', 'receiverPublicKey', 'settlementExpiration', 'nonce', 'assetId', 'collateralId', 'resolution']);
|
|
1911
|
+
const response = await this.v1PrivatePostUserTransfer(this.extend(request, params));
|
|
1912
|
+
//
|
|
1913
|
+
// {
|
|
1914
|
+
// "status": "OK",
|
|
1915
|
+
// "data": {
|
|
1916
|
+
// "validSignature": true,
|
|
1917
|
+
// "id": 1820778187672010752
|
|
1918
|
+
// }
|
|
1919
|
+
// }
|
|
1920
|
+
//
|
|
1921
|
+
const data = this.safeDict(response, 'data', {});
|
|
1922
|
+
const validSignature = this.safeBool(data, 'validSignature');
|
|
1923
|
+
const now = this.milliseconds();
|
|
1924
|
+
let status = 'pending';
|
|
1925
|
+
if (validSignature !== undefined) {
|
|
1926
|
+
status = validSignature ? 'ok' : 'failed';
|
|
1927
|
+
}
|
|
1928
|
+
return {
|
|
1929
|
+
'info': response,
|
|
1930
|
+
'id': this.safeString(data, 'id'),
|
|
1931
|
+
'timestamp': now,
|
|
1932
|
+
'datetime': this.iso8601(now),
|
|
1933
|
+
'currency': currency['code'],
|
|
1934
|
+
'amount': this.parseNumber(amountString),
|
|
1935
|
+
'fromAccount': fromAccount,
|
|
1936
|
+
'toAccount': toAccount,
|
|
1937
|
+
'status': status,
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
parseTransfer(transfer, currency = undefined) {
|
|
1941
|
+
const timestamp = this.safeInteger(transfer, 'time');
|
|
1942
|
+
const assetId = this.safeString(transfer, 'asset');
|
|
1943
|
+
const code = this.getExtendedCurrencyCodeById(assetId, currency);
|
|
1944
|
+
const amountString = this.safeString(transfer, 'amount');
|
|
1945
|
+
const amount = (amountString === undefined) ? undefined : this.parseNumber(Precise["default"].stringAbs(amountString));
|
|
1946
|
+
const accountId = this.safeString(transfer, 'accountId');
|
|
1947
|
+
const counterpartyAccountId = this.safeString(transfer, 'counterpartyAccountId');
|
|
1948
|
+
let fromAccount = accountId;
|
|
1949
|
+
let toAccount = counterpartyAccountId;
|
|
1950
|
+
if ((amountString !== undefined) && !Precise["default"].stringLt(amountString, '0')) {
|
|
1951
|
+
fromAccount = counterpartyAccountId;
|
|
1952
|
+
toAccount = accountId;
|
|
1953
|
+
}
|
|
1954
|
+
const validSignature = this.safeBool(transfer, 'validSignature');
|
|
1955
|
+
let status = undefined;
|
|
1956
|
+
if (validSignature !== undefined) {
|
|
1957
|
+
status = validSignature ? 'ok' : 'failed';
|
|
1958
|
+
}
|
|
1959
|
+
else {
|
|
1960
|
+
status = this.parseTransactionStatus(this.safeString(transfer, 'status'));
|
|
1961
|
+
}
|
|
1962
|
+
return {
|
|
1963
|
+
'info': transfer,
|
|
1964
|
+
'id': this.safeString(transfer, 'id'),
|
|
1965
|
+
'timestamp': timestamp,
|
|
1966
|
+
'datetime': this.iso8601(timestamp),
|
|
1967
|
+
'currency': code,
|
|
1968
|
+
'amount': amount,
|
|
1969
|
+
'fromAccount': fromAccount,
|
|
1970
|
+
'toAccount': toAccount,
|
|
1971
|
+
'status': status,
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
getExtendedCurrencyCodeById(assetId, currency = undefined) {
|
|
1975
|
+
if (assetId === undefined) {
|
|
1976
|
+
return this.safeString(currency, 'code');
|
|
1977
|
+
}
|
|
1978
|
+
const currenciesByNumericId = this.safeDict(this.options, 'currenciesByNumericId', {});
|
|
1979
|
+
const currencyByNumericId = this.safeDict(currenciesByNumericId, assetId);
|
|
1980
|
+
if (currencyByNumericId !== undefined) {
|
|
1981
|
+
return this.safeString(currencyByNumericId, 'code');
|
|
1982
|
+
}
|
|
1983
|
+
if (currency !== undefined) {
|
|
1984
|
+
return currency['code'];
|
|
1985
|
+
}
|
|
1986
|
+
let code = this.safeCurrencyCode(assetId);
|
|
1987
|
+
if (code === 'USD') {
|
|
1988
|
+
code = 'USDC';
|
|
1989
|
+
}
|
|
1990
|
+
return code;
|
|
1991
|
+
}
|
|
1992
|
+
parseTransactionStatus(status) {
|
|
1993
|
+
const statuses = {
|
|
1994
|
+
'CREATED': 'pending',
|
|
1995
|
+
'IN_PROGRESS': 'pending',
|
|
1996
|
+
'COMPLETED': 'ok',
|
|
1997
|
+
'REJECTED': 'failed',
|
|
1998
|
+
};
|
|
1999
|
+
return this.safeString(statuses, status, status);
|
|
2000
|
+
}
|
|
2001
|
+
parseTransactionType(type) {
|
|
2002
|
+
const types = {
|
|
2003
|
+
'DEPOSIT': 'deposit',
|
|
2004
|
+
'WITHDRAWAL': 'withdrawal',
|
|
2005
|
+
'TRANSFER': 'transfer',
|
|
2006
|
+
'CLAIM': 'claim',
|
|
2007
|
+
};
|
|
2008
|
+
return this.safeString(types, type, type);
|
|
2009
|
+
}
|
|
2010
|
+
parseTransaction(transaction, currency = undefined) {
|
|
2011
|
+
//
|
|
2012
|
+
// {
|
|
2013
|
+
// "id": "1951255127004282880",
|
|
2014
|
+
// "type": "TRANSFER",
|
|
2015
|
+
// "status": "COMPLETED",
|
|
2016
|
+
// "amount": "-3.0000000000000000",
|
|
2017
|
+
// "fee": "0",
|
|
2018
|
+
// "asset": 1,
|
|
2019
|
+
// "time": 1754050449502,
|
|
2020
|
+
// "accountId": 100009,
|
|
2021
|
+
// "counterpartyAccountId": 100023
|
|
2022
|
+
// }
|
|
2023
|
+
//
|
|
2024
|
+
const timestamp = this.safeInteger(transaction, 'time');
|
|
2025
|
+
const assetId = this.safeString(transaction, 'asset');
|
|
2026
|
+
const code = this.getExtendedCurrencyCodeById(assetId, currency);
|
|
2027
|
+
const amountString = this.safeString(transaction, 'amount');
|
|
2028
|
+
const amount = (amountString === undefined) ? undefined : this.parseNumber(Precise["default"].stringAbs(amountString));
|
|
2029
|
+
let fee = undefined;
|
|
2030
|
+
const feeCost = this.safeString(transaction, 'fee');
|
|
2031
|
+
if (feeCost !== undefined) {
|
|
2032
|
+
fee = {
|
|
2033
|
+
'currency': code,
|
|
2034
|
+
'cost': this.parseNumber(Precise["default"].stringAbs(feeCost)),
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
2037
|
+
const transactionType = this.parseTransactionType(this.safeString(transaction, 'type'));
|
|
2038
|
+
const network = this.safeString(transaction, 'chain');
|
|
2039
|
+
return {
|
|
2040
|
+
'info': transaction,
|
|
2041
|
+
'id': this.safeString(transaction, 'id'),
|
|
2042
|
+
'txid': this.safeString(transaction, 'transactionHash'),
|
|
2043
|
+
'timestamp': timestamp,
|
|
2044
|
+
'datetime': this.iso8601(timestamp),
|
|
2045
|
+
'address': undefined,
|
|
2046
|
+
'addressFrom': undefined,
|
|
2047
|
+
'addressTo': undefined,
|
|
2048
|
+
'tag': undefined,
|
|
2049
|
+
'tagFrom': undefined,
|
|
2050
|
+
'tagTo': undefined,
|
|
2051
|
+
'type': transactionType,
|
|
2052
|
+
'amount': amount,
|
|
2053
|
+
'currency': code,
|
|
2054
|
+
'status': this.parseTransactionStatus(this.safeString(transaction, 'status')),
|
|
2055
|
+
'updated': timestamp,
|
|
2056
|
+
'fee': fee,
|
|
2057
|
+
'network': network,
|
|
2058
|
+
'comment': undefined,
|
|
2059
|
+
'internal': (transactionType === 'transfer'),
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
/**
|
|
2063
|
+
* @method
|
|
2064
|
+
* @name extended#fetchTradingFee
|
|
2065
|
+
* @description fetch the trading fees for a market
|
|
2066
|
+
* @see https://api.docs.extended.exchange/#get-fees
|
|
2067
|
+
* @param {string} symbol unified market symbol
|
|
2068
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2069
|
+
* @param {string} [params.builderId] builder client id
|
|
2070
|
+
* @returns {object} a [fee structure]{@link https://docs.ccxt.com/?id=fee-structure}
|
|
2071
|
+
*/
|
|
2072
|
+
async fetchTradingFee(symbol, params = {}) {
|
|
2073
|
+
await this.loadMarkets();
|
|
2074
|
+
const market = this.market(symbol);
|
|
2075
|
+
const request = {
|
|
2076
|
+
'market': market['id'],
|
|
2077
|
+
};
|
|
2078
|
+
const response = await this.v1PrivateGetUserFees(this.extend(request, params));
|
|
2079
|
+
//
|
|
2080
|
+
// {
|
|
2081
|
+
// "status": "OK",
|
|
2082
|
+
// "data": [
|
|
2083
|
+
// {
|
|
2084
|
+
// "market": "BTC-USD",
|
|
2085
|
+
// "makerFeeRate": "0.00000",
|
|
2086
|
+
// "takerFeeRate": "0.00025",
|
|
2087
|
+
// "builderFeeRate": "0.0001"
|
|
2088
|
+
// }
|
|
2089
|
+
// ]
|
|
2090
|
+
// }
|
|
2091
|
+
//
|
|
2092
|
+
const data = this.safeList(response, 'data', []);
|
|
2093
|
+
const first = this.safeDict(data, 0, {});
|
|
2094
|
+
return this.parseTradingFee(first, market);
|
|
2095
|
+
}
|
|
2096
|
+
/**
|
|
2097
|
+
* @method
|
|
2098
|
+
* @name extended#fetchTradingFees
|
|
2099
|
+
* @description fetch the trading fees for multiple markets
|
|
2100
|
+
* @see https://api.docs.extended.exchange/#get-fees
|
|
2101
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2102
|
+
* @param {string} [params.market] exchange market id
|
|
2103
|
+
* @param {string} [params.builderId] builder client id
|
|
2104
|
+
* @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/?id=fee-structure} indexed by market symbols
|
|
2105
|
+
*/
|
|
2106
|
+
async fetchTradingFees(params = {}) {
|
|
2107
|
+
await this.loadMarkets();
|
|
2108
|
+
const response = await this.v1PrivateGetUserFees(params);
|
|
2109
|
+
//
|
|
2110
|
+
// {
|
|
2111
|
+
// "status": "OK",
|
|
2112
|
+
// "data": [
|
|
2113
|
+
// {
|
|
2114
|
+
// "market": "BTC-USD",
|
|
2115
|
+
// "makerFeeRate": "0.00000",
|
|
2116
|
+
// "takerFeeRate": "0.00025",
|
|
2117
|
+
// "builderFeeRate": "0.0001"
|
|
2118
|
+
// }
|
|
2119
|
+
// ]
|
|
2120
|
+
// }
|
|
2121
|
+
//
|
|
2122
|
+
const data = this.safeList(response, 'data', []);
|
|
2123
|
+
const result = {};
|
|
2124
|
+
for (let i = 0; i < data.length; i++) {
|
|
2125
|
+
const fee = this.safeDict(data, i, {});
|
|
2126
|
+
const parsed = this.parseTradingFee(fee);
|
|
2127
|
+
const symbol = this.safeString(parsed, 'symbol');
|
|
2128
|
+
result[symbol] = parsed;
|
|
2129
|
+
}
|
|
2130
|
+
return result;
|
|
2131
|
+
}
|
|
2132
|
+
parseTradingFee(fee, market = undefined) {
|
|
2133
|
+
//
|
|
2134
|
+
// {
|
|
2135
|
+
// "market": "BTC-USD",
|
|
2136
|
+
// "makerFeeRate": "0.00000",
|
|
2137
|
+
// "takerFeeRate": "0.00025",
|
|
2138
|
+
// "builderFeeRate": "0.0001"
|
|
2139
|
+
// }
|
|
2140
|
+
//
|
|
2141
|
+
const marketId = this.safeString(fee, 'market');
|
|
2142
|
+
market = this.safeMarket(marketId, market);
|
|
2143
|
+
return {
|
|
2144
|
+
'info': fee,
|
|
2145
|
+
'symbol': market['symbol'],
|
|
2146
|
+
'maker': this.safeNumber(fee, 'makerFeeRate'),
|
|
2147
|
+
'taker': this.safeNumber(fee, 'takerFeeRate'),
|
|
2148
|
+
'percentage': true,
|
|
2149
|
+
'tierBased': undefined,
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
/**
|
|
2153
|
+
* @method
|
|
2154
|
+
* @name extended#fetchLeverage
|
|
2155
|
+
* @description fetch the set leverage for a market
|
|
2156
|
+
* @see https://api.docs.extended.exchange/#get-leverage
|
|
2157
|
+
* @param {string} symbol unified market symbol
|
|
2158
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2159
|
+
* @returns {object} a [leverage structure]{@link https://docs.ccxt.com/#/?id=leverage-structure}
|
|
2160
|
+
*/
|
|
2161
|
+
async fetchLeverage(symbol, params = {}) {
|
|
2162
|
+
await this.loadMarkets();
|
|
2163
|
+
const market = this.market(symbol);
|
|
2164
|
+
const request = {
|
|
2165
|
+
'market': market['id'],
|
|
2166
|
+
};
|
|
2167
|
+
const response = await this.v1PrivateGetUserLeverage(this.extend(request, params));
|
|
2168
|
+
//
|
|
2169
|
+
// {
|
|
2170
|
+
// "status": "OK",
|
|
2171
|
+
// "data": [
|
|
2172
|
+
// {
|
|
2173
|
+
// "market": "SOL-USD",
|
|
2174
|
+
// "leverage": "10"
|
|
2175
|
+
// }
|
|
2176
|
+
// ]
|
|
2177
|
+
// }
|
|
2178
|
+
//
|
|
2179
|
+
const data = this.safeList(response, 'data', []);
|
|
2180
|
+
return this.parseLeverage(this.safeDict(data, 0), market);
|
|
2181
|
+
}
|
|
2182
|
+
/**
|
|
2183
|
+
* @method
|
|
2184
|
+
* @name extended#setLeverage
|
|
2185
|
+
* @description set the level of leverage for a market
|
|
2186
|
+
* @see https://api.docs.extended.exchange/#update-leverage
|
|
2187
|
+
* @param {int} leverage the rate of leverage
|
|
2188
|
+
* @param {string} symbol unified market symbol
|
|
2189
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2190
|
+
* @returns {object} response from the exchange
|
|
2191
|
+
*/
|
|
2192
|
+
async setLeverage(leverage, symbol = undefined, params = {}) {
|
|
2193
|
+
if (symbol === undefined) {
|
|
2194
|
+
throw new errors.ArgumentsRequired(this.id + ' setLeverage() requires a symbol argument');
|
|
2195
|
+
}
|
|
2196
|
+
await this.loadMarkets();
|
|
2197
|
+
const market = this.market(symbol);
|
|
2198
|
+
const request = {
|
|
2199
|
+
'market': market['id'],
|
|
2200
|
+
'leverage': this.numberToString(leverage),
|
|
2201
|
+
};
|
|
2202
|
+
const response = await this.v1PrivatePatchUserLeverage(this.extend(request, params));
|
|
2203
|
+
//
|
|
2204
|
+
// {
|
|
2205
|
+
// "status": "OK",
|
|
2206
|
+
// "data": {}
|
|
2207
|
+
// }
|
|
2208
|
+
//
|
|
2209
|
+
const data = this.safeDict(response, 'data', {});
|
|
2210
|
+
return this.parseLeverage(data, market);
|
|
2211
|
+
}
|
|
2212
|
+
parseLeverage(leverage, market = undefined) {
|
|
2213
|
+
//
|
|
2214
|
+
// {
|
|
2215
|
+
// "market": "BTC-USD",
|
|
2216
|
+
// "leverage": "10"
|
|
2217
|
+
// }
|
|
2218
|
+
//
|
|
2219
|
+
const marketId = this.safeString(leverage, 'market');
|
|
2220
|
+
market = this.safeMarket(marketId, market);
|
|
2221
|
+
const leverageValue = this.safeNumber(leverage, 'leverage');
|
|
2222
|
+
return {
|
|
2223
|
+
'info': leverage,
|
|
2224
|
+
'symbol': market['symbol'],
|
|
2225
|
+
'marginMode': undefined,
|
|
2226
|
+
'longLeverage': leverageValue,
|
|
2227
|
+
'shortLeverage': leverageValue,
|
|
2228
|
+
};
|
|
2229
|
+
}
|
|
2230
|
+
/**
|
|
2231
|
+
* @method
|
|
2232
|
+
* @name extended#fetchPositions
|
|
2233
|
+
* @description fetch all open positions
|
|
2234
|
+
* @see https://api.docs.extended.exchange/#get-positions
|
|
2235
|
+
* @param {string[]|undefined} symbols list of unified market symbols
|
|
2236
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2237
|
+
* @returns {Position[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
2238
|
+
*/
|
|
2239
|
+
async fetchPositions(symbols = undefined, params = {}) {
|
|
2240
|
+
await this.loadMarkets();
|
|
2241
|
+
const request = {};
|
|
2242
|
+
if (symbols !== undefined) {
|
|
2243
|
+
const marketIds = this.marketIds(symbols);
|
|
2244
|
+
request['market'] = marketIds;
|
|
2245
|
+
}
|
|
2246
|
+
const response = await this.v1PrivateGetUserPositions(this.extend(request, params));
|
|
2247
|
+
//
|
|
2248
|
+
// {
|
|
2249
|
+
// "status": "OK",
|
|
2250
|
+
// "data": [
|
|
2251
|
+
// {
|
|
2252
|
+
// "id": 1,
|
|
2253
|
+
// "accountId": 1,
|
|
2254
|
+
// "market": "BTC-USD",
|
|
2255
|
+
// "side": "LONG",
|
|
2256
|
+
// "leverage": "10",
|
|
2257
|
+
// "size": "0.1",
|
|
2258
|
+
// "value": "4000",
|
|
2259
|
+
// "openPrice": "39000",
|
|
2260
|
+
// "markPrice": "40000",
|
|
2261
|
+
// "liquidationPrice": "38200",
|
|
2262
|
+
// "margin": "20",
|
|
2263
|
+
// "unrealisedPnl": "1000",
|
|
2264
|
+
// "realisedPnl": "1.2",
|
|
2265
|
+
// "tpTriggerPrice": "41000",
|
|
2266
|
+
// "tpLimitPrice": "41500",
|
|
2267
|
+
// "slTriggerPrice": "39500",
|
|
2268
|
+
// "slLimitPrice": "39000",
|
|
2269
|
+
// "adl": "2.5",
|
|
2270
|
+
// "maxPositionSize": "0.2",
|
|
2271
|
+
// "createdAt": 1701563440000,
|
|
2272
|
+
// "updatedAt": 1701563440000
|
|
2273
|
+
// }
|
|
2274
|
+
// ]
|
|
2275
|
+
// }
|
|
2276
|
+
//
|
|
2277
|
+
const data = this.safeList(response, 'data', []);
|
|
2278
|
+
return this.parsePositions(data, symbols);
|
|
2279
|
+
}
|
|
2280
|
+
/**
|
|
2281
|
+
* @method
|
|
2282
|
+
* @name extended#fetchPosition
|
|
2283
|
+
* @description fetch data on an open position
|
|
2284
|
+
* @see https://api.docs.extended.exchange/#get-positions
|
|
2285
|
+
* @param {string} symbol unified market symbol of the market the position is held in
|
|
2286
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2287
|
+
* @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
2288
|
+
*/
|
|
2289
|
+
async fetchPosition(symbol, params = {}) {
|
|
2290
|
+
const positions = await this.fetchPositions([symbol], params);
|
|
2291
|
+
return this.safeDict(positions, 0);
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* @method
|
|
2295
|
+
* @name extended#fetchPositionsHistory
|
|
2296
|
+
* @description fetch historical positions
|
|
2297
|
+
* @see https://api.docs.extended.exchange/#get-positions-history
|
|
2298
|
+
* @param {string[]|undefined} symbols list of unified market symbols
|
|
2299
|
+
* @param {int} [since] the earliest time in ms to fetch positions for
|
|
2300
|
+
* @param {int} [limit] the maximum number of position structures to retrieve
|
|
2301
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2302
|
+
* @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)
|
|
2303
|
+
* @returns {Position[]} a list of [position structures]{@link https://docs.ccxt.com/#/?id=position-structure}
|
|
2304
|
+
*/
|
|
2305
|
+
async fetchPositionsHistory(symbols = undefined, since = undefined, limit = undefined, params = {}) {
|
|
2306
|
+
await this.loadMarkets();
|
|
2307
|
+
if (typeof symbols === 'string') {
|
|
2308
|
+
symbols = [symbols];
|
|
2309
|
+
}
|
|
2310
|
+
let paginate = false;
|
|
2311
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchPositionsHistory', 'paginate');
|
|
2312
|
+
if (paginate) {
|
|
2313
|
+
return await this.fetchPaginatedCallCursor('fetchPositionsHistory', symbols, since, limit, params, 'cursor', 'cursor', undefined, 10000);
|
|
2314
|
+
}
|
|
2315
|
+
const request = {};
|
|
2316
|
+
if (symbols !== undefined) {
|
|
2317
|
+
const marketIds = this.marketIds(symbols);
|
|
2318
|
+
request['market'] = marketIds;
|
|
2319
|
+
}
|
|
2320
|
+
const response = await this.v1PrivateGetUserPositionsHistory(this.extend(request, params));
|
|
2321
|
+
//
|
|
2322
|
+
// {
|
|
2323
|
+
// "status": "OK",
|
|
2324
|
+
// "data": [
|
|
2325
|
+
// {
|
|
2326
|
+
// "id": 1784963886257016832,
|
|
2327
|
+
// "accountId": 1,
|
|
2328
|
+
// "market": "BTC-USD",
|
|
2329
|
+
// "side": "LONG",
|
|
2330
|
+
// "exitType": "TRADE",
|
|
2331
|
+
// "leverage": "10",
|
|
2332
|
+
// "size": "0.1",
|
|
2333
|
+
// "maxPositionSize": "0.2",
|
|
2334
|
+
// "openPrice": "39000",
|
|
2335
|
+
// "exitPrice": "40000",
|
|
2336
|
+
// "realisedPnl": "10",
|
|
2337
|
+
// "createdTime": 1701563440000,
|
|
2338
|
+
// "closedTime": 1701567040000
|
|
2339
|
+
// }
|
|
2340
|
+
// ],
|
|
2341
|
+
// "pagination": {
|
|
2342
|
+
// "cursor": 1784963886257016832,
|
|
2343
|
+
// "count": 1
|
|
2344
|
+
// }
|
|
2345
|
+
// }
|
|
2346
|
+
//
|
|
2347
|
+
const data = this.safeList(response, 'data', []);
|
|
2348
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
2349
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
2350
|
+
const result = [];
|
|
2351
|
+
const dataLength = data.length;
|
|
2352
|
+
for (let i = 0; i < dataLength; i++) {
|
|
2353
|
+
let entry = data[i];
|
|
2354
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
2355
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
2356
|
+
}
|
|
2357
|
+
result.push(entry);
|
|
2358
|
+
}
|
|
2359
|
+
const positions = this.parsePositions(result, symbols);
|
|
2360
|
+
return this.filterBySinceLimit(positions, since, limit, 'timestamp');
|
|
2361
|
+
}
|
|
2362
|
+
parsePosition(position, market = undefined) {
|
|
2363
|
+
//
|
|
2364
|
+
// {
|
|
2365
|
+
// "id": 1,
|
|
2366
|
+
// "accountId": 1,
|
|
2367
|
+
// "market": "BTC-USD",
|
|
2368
|
+
// "side": "LONG",
|
|
2369
|
+
// "leverage": "10",
|
|
2370
|
+
// "size": "0.1",
|
|
2371
|
+
// "value": "4000",
|
|
2372
|
+
// "openPrice": "39000",
|
|
2373
|
+
// "markPrice": "40000",
|
|
2374
|
+
// "liquidationPrice": "38200",
|
|
2375
|
+
// "margin": "20",
|
|
2376
|
+
// "unrealisedPnl": "1000",
|
|
2377
|
+
// "realisedPnl": "1.2",
|
|
2378
|
+
// "tpTriggerPrice": "41000",
|
|
2379
|
+
// "tpLimitPrice": "41500",
|
|
2380
|
+
// "slTriggerPrice": "39500",
|
|
2381
|
+
// "slLimitPrice": "39000",
|
|
2382
|
+
// "adl": "2.5",
|
|
2383
|
+
// "maxPositionSize": "0.2",
|
|
2384
|
+
// "createdAt": 1701563440000,
|
|
2385
|
+
// "updatedAt": 1701563440000
|
|
2386
|
+
// }
|
|
2387
|
+
//
|
|
2388
|
+
const marketId = this.safeString(position, 'market');
|
|
2389
|
+
market = this.safeMarket(marketId, market);
|
|
2390
|
+
const timestamp = this.safeInteger2(position, 'createdAt', 'createdTime');
|
|
2391
|
+
let lastUpdateTimestamp = this.safeInteger2(position, 'updatedAt', 'updatedTime');
|
|
2392
|
+
lastUpdateTimestamp = this.safeInteger(position, 'closedTime', lastUpdateTimestamp);
|
|
2393
|
+
const side = this.safeStringLower(position, 'side');
|
|
2394
|
+
const margin = this.safeString(position, 'margin');
|
|
2395
|
+
return this.safePosition({
|
|
2396
|
+
'info': position,
|
|
2397
|
+
'id': this.safeString(position, 'id'),
|
|
2398
|
+
'symbol': market['symbol'],
|
|
2399
|
+
'timestamp': timestamp,
|
|
2400
|
+
'datetime': this.iso8601(timestamp),
|
|
2401
|
+
'lastUpdateTimestamp': lastUpdateTimestamp,
|
|
2402
|
+
'initialMargin': margin,
|
|
2403
|
+
'initialMarginPercentage': undefined,
|
|
2404
|
+
'maintenanceMargin': undefined,
|
|
2405
|
+
'maintenanceMarginPercentage': undefined,
|
|
2406
|
+
'entryPrice': this.safeString(position, 'openPrice'),
|
|
2407
|
+
'notional': this.safeString(position, 'value'),
|
|
2408
|
+
'leverage': this.safeString(position, 'leverage'),
|
|
2409
|
+
'unrealizedPnl': this.safeString(position, 'unrealisedPnl'),
|
|
2410
|
+
'realizedPnl': this.safeString(position, 'realisedPnl'),
|
|
2411
|
+
'contracts': this.safeString(position, 'size'),
|
|
2412
|
+
'contractSize': this.safeString(market, 'contractSize'),
|
|
2413
|
+
'marginRatio': undefined,
|
|
2414
|
+
'liquidationPrice': this.safeString(position, 'liquidationPrice'),
|
|
2415
|
+
'markPrice': this.safeString(position, 'markPrice'),
|
|
2416
|
+
'lastPrice': this.safeString(position, 'exitPrice'),
|
|
2417
|
+
'collateral': margin,
|
|
2418
|
+
'marginMode': undefined,
|
|
2419
|
+
'side': side,
|
|
2420
|
+
'percentage': undefined,
|
|
2421
|
+
'hedged': undefined,
|
|
2422
|
+
'stopLossPrice': this.safeString(position, 'slTriggerPrice'),
|
|
2423
|
+
'takeProfitPrice': this.safeString(position, 'tpTriggerPrice'),
|
|
2424
|
+
});
|
|
2425
|
+
}
|
|
2426
|
+
getExtendedStarkAmount(amount, resolution, roundUp = false) {
|
|
2427
|
+
const resolutionString = this.numberToString(resolution);
|
|
2428
|
+
const precise = Precise["default"].stringMul(amount, resolutionString);
|
|
2429
|
+
let result = this.decimalToPrecision(precise, number.TRUNCATE, 0, number.DECIMAL_PLACES, number.NO_PADDING);
|
|
2430
|
+
if (roundUp && Precise["default"].stringGt(precise, result)) {
|
|
2431
|
+
result = Precise["default"].stringAdd(result, '1');
|
|
2432
|
+
}
|
|
2433
|
+
return result;
|
|
2434
|
+
}
|
|
2435
|
+
async fetchExtendedAccount(params = {}) {
|
|
2436
|
+
let account = this.safeDict(this.options, 'account');
|
|
2437
|
+
if (account !== undefined) {
|
|
2438
|
+
return account;
|
|
2439
|
+
}
|
|
2440
|
+
const accountData = await this.fetchAccount(params);
|
|
2441
|
+
account = accountData['info'];
|
|
2442
|
+
this.options['account'] = account;
|
|
2443
|
+
return account;
|
|
2444
|
+
}
|
|
2445
|
+
createOrderSettlementData(isBuy, amountString, priceString, params = {}) {
|
|
2446
|
+
const totalFee = this.safeString(params, 'totalFee');
|
|
2447
|
+
const settlementExpiration = this.safeInteger(params, 'settlementExpiration');
|
|
2448
|
+
const nonce = this.safeInteger(params, 'nonce');
|
|
2449
|
+
const starkKey = this.safeString(params, 'starkKey');
|
|
2450
|
+
const collateralPosition = this.safeString(params, 'collateralPosition');
|
|
2451
|
+
const syntheticId = this.safeString(params, 'syntheticId');
|
|
2452
|
+
const collateralId = this.safeString(params, 'collateralId');
|
|
2453
|
+
const syntheticResolution = this.safeInteger(params, 'syntheticResolution');
|
|
2454
|
+
const collateralResolution = this.safeInteger(params, 'collateralResolution');
|
|
2455
|
+
const quoteAmount = Precise["default"].stringMul(amountString, priceString);
|
|
2456
|
+
const baseRoundUp = isBuy;
|
|
2457
|
+
const quoteRoundUp = isBuy;
|
|
2458
|
+
let baseAmount = this.getExtendedStarkAmount(amountString, syntheticResolution, baseRoundUp);
|
|
2459
|
+
let collateralAmount = this.getExtendedStarkAmount(quoteAmount, collateralResolution, quoteRoundUp);
|
|
2460
|
+
if (isBuy) {
|
|
2461
|
+
collateralAmount = Precise["default"].stringNeg(collateralAmount);
|
|
2462
|
+
}
|
|
2463
|
+
else {
|
|
2464
|
+
baseAmount = Precise["default"].stringNeg(baseAmount);
|
|
2465
|
+
}
|
|
2466
|
+
const feeAmount = this.getExtendedStarkAmount(Precise["default"].stringMul(totalFee, quoteAmount), collateralResolution, true);
|
|
2467
|
+
const settlement = {
|
|
2468
|
+
'starkKey': starkKey,
|
|
2469
|
+
'collateralPosition': collateralPosition,
|
|
2470
|
+
'baseAssetId': syntheticId,
|
|
2471
|
+
'baseAmount': baseAmount,
|
|
2472
|
+
'quoteAssetId': collateralId,
|
|
2473
|
+
'quoteAmount': collateralAmount,
|
|
2474
|
+
'feeAssetId': collateralId,
|
|
2475
|
+
'feeAmount': feeAmount,
|
|
2476
|
+
'expiration': this.numberToString(settlementExpiration),
|
|
2477
|
+
'salt': nonce,
|
|
2478
|
+
};
|
|
2479
|
+
const msgHash = this.getExtendedOrderMsgHash(settlement);
|
|
2480
|
+
const sig = JSON.parse(this.extendedStarknetSign(msgHash, this.privateKey));
|
|
2481
|
+
const r = this.getExtendedSignatureHex(sig[0]);
|
|
2482
|
+
const s = this.getExtendedSignatureHex(sig[1]);
|
|
2483
|
+
settlement['r'] = r;
|
|
2484
|
+
settlement['s'] = s;
|
|
2485
|
+
return settlement;
|
|
2486
|
+
}
|
|
2487
|
+
createWithdrawalSettlementData(address, amountString, currency, account, params = {}) {
|
|
2488
|
+
const now = this.milliseconds();
|
|
2489
|
+
const settlementExpiration = this.safeInteger(params, 'settlementExpiration', this.parseToInt((now + 999) / 1000) + 1209600 + 60);
|
|
2490
|
+
const nonce = this.safeInteger(params, 'nonce', this.nonce());
|
|
2491
|
+
const positionId = this.safeString2(params, 'positionId', 'l2Vault', this.safeString(account, 'l2Vault'));
|
|
2492
|
+
const recipient = this.safeString(params, 'recipient', address);
|
|
2493
|
+
const currencyInfo = this.safeDict(currency, 'info', {});
|
|
2494
|
+
const collateralId = this.safeString(params, 'collateralId', this.safeString2(currencyInfo, 'starkexId', 'l1Id'));
|
|
2495
|
+
const resolution = this.safeInteger(params, 'resolution', this.safeValue2(currencyInfo, 'starkexResolution', 'l1Resolution'));
|
|
2496
|
+
const starkKey = this.safeString(account, 'l2Key');
|
|
2497
|
+
if ((positionId === undefined) || (collateralId === undefined) || (resolution === undefined) || (starkKey === undefined)) {
|
|
2498
|
+
throw new errors.BadRequest(this.id + ' withdraw() requires currency starkexId/starkexResolution, account l2Vault and account l2Key');
|
|
2499
|
+
}
|
|
2500
|
+
const amount = this.getExtendedStarkAmount(amountString, resolution);
|
|
2501
|
+
const settlement = {
|
|
2502
|
+
'recipient': recipient,
|
|
2503
|
+
'positionId': positionId,
|
|
2504
|
+
'collateralId': collateralId,
|
|
2505
|
+
'amount': amount,
|
|
2506
|
+
'expiration': {
|
|
2507
|
+
'seconds': settlementExpiration,
|
|
2508
|
+
},
|
|
2509
|
+
'salt': nonce,
|
|
2510
|
+
};
|
|
2511
|
+
const msgHash = this.getExtendedWithdrawalMsgHash(settlement, starkKey);
|
|
2512
|
+
const sig = JSON.parse(this.extendedStarknetSign(msgHash, this.privateKey));
|
|
2513
|
+
settlement['signature'] = {
|
|
2514
|
+
'r': this.getExtendedSignatureHex(sig[0]),
|
|
2515
|
+
's': this.getExtendedSignatureHex(sig[1]),
|
|
2516
|
+
};
|
|
2517
|
+
return settlement;
|
|
2518
|
+
}
|
|
2519
|
+
createTransferSettlementData(amountString, currency, account, toVault, toL2Key, params = {}) {
|
|
2520
|
+
const now = this.milliseconds();
|
|
2521
|
+
const settlementExpiration = this.safeInteger(params, 'settlementExpiration', this.parseToInt((now + 999) / 1000) + 1814400);
|
|
2522
|
+
const nonce = this.safeInteger(params, 'nonce', this.nonce());
|
|
2523
|
+
const fromVault = this.safeString2(params, 'fromVault', 'senderPositionId', this.safeString(account, 'l2Vault'));
|
|
2524
|
+
const fromL2Key = this.safeString2(params, 'fromL2Key', 'senderPublicKey', this.safeString(account, 'l2Key'));
|
|
2525
|
+
const currencyInfo = this.safeDict(currency, 'info', {});
|
|
2526
|
+
const collateralId = this.safeString2(params, 'assetId', 'collateralId', this.safeString2(currencyInfo, 'starkexId', 'l1Id'));
|
|
2527
|
+
const resolution = this.safeInteger(params, 'resolution', this.safeValue2(currencyInfo, 'starkexResolution', 'l1Resolution'));
|
|
2528
|
+
if ((fromVault === undefined) || (fromL2Key === undefined) || (collateralId === undefined) || (resolution === undefined)) {
|
|
2529
|
+
throw new errors.BadRequest(this.id + ' transfer() requires currency starkexId/starkexResolution, account l2Vault and account l2Key');
|
|
2530
|
+
}
|
|
2531
|
+
const transferAmount = this.getExtendedStarkAmount(amountString, resolution);
|
|
2532
|
+
const settlement = {
|
|
2533
|
+
'amount': transferAmount,
|
|
2534
|
+
'assetId': collateralId,
|
|
2535
|
+
'expirationTimestamp': settlementExpiration,
|
|
2536
|
+
'nonce': nonce,
|
|
2537
|
+
'receiverPositionId': toVault,
|
|
2538
|
+
'receiverPublicKey': toL2Key,
|
|
2539
|
+
'senderPositionId': fromVault,
|
|
2540
|
+
'senderPublicKey': fromL2Key,
|
|
2541
|
+
};
|
|
2542
|
+
const msgHash = this.getExtendedTransferMsgHash(settlement);
|
|
2543
|
+
const sig = JSON.parse(this.extendedStarknetSign(msgHash, this.privateKey));
|
|
2544
|
+
settlement['signature'] = {
|
|
2545
|
+
'r': this.getExtendedSignatureHex(sig[0]),
|
|
2546
|
+
's': this.getExtendedSignatureHex(sig[1]),
|
|
2547
|
+
};
|
|
2548
|
+
return settlement;
|
|
2549
|
+
}
|
|
2550
|
+
async createExtendedOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
|
|
2551
|
+
await this.loadMarkets();
|
|
2552
|
+
const market = this.market(symbol);
|
|
2553
|
+
const uppercaseType = type.toUpperCase();
|
|
2554
|
+
const uppercaseSide = side.toUpperCase();
|
|
2555
|
+
if (market['spot'] && uppercaseType !== 'LIMIT') {
|
|
2556
|
+
throw new errors.BadRequest(this.id + ' createOrder() supports limit orders for spot markets only');
|
|
2557
|
+
}
|
|
2558
|
+
if (!this.inArray(uppercaseType, ['LIMIT', 'MARKET', 'CONDITIONAL', 'TPSL'])) {
|
|
2559
|
+
throw new errors.BadRequest(this.id + ' createOrder() supports limit, market, conditional and tpsl orders only');
|
|
2560
|
+
}
|
|
2561
|
+
if (price === undefined) {
|
|
2562
|
+
throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a price argument');
|
|
2563
|
+
}
|
|
2564
|
+
const amountString = this.amountToPrecision(symbol, amount);
|
|
2565
|
+
const priceString = this.priceToPrecision(symbol, price);
|
|
2566
|
+
const postOnly = this.isPostOnly(uppercaseType === 'MARKET', undefined, params);
|
|
2567
|
+
const reduceOnly = this.safeBool2(params, 'reduceOnly', 'reduce_only', false);
|
|
2568
|
+
let timeInForce = this.safeStringUpper(params, 'timeInForce');
|
|
2569
|
+
if (timeInForce === undefined) {
|
|
2570
|
+
timeInForce = (uppercaseType === 'MARKET') ? 'IOC' : 'GTT';
|
|
2571
|
+
}
|
|
2572
|
+
const fee = this.safeString(params, 'fee', '0.0005');
|
|
2573
|
+
let builderFeeRate = undefined;
|
|
2574
|
+
let builderId = undefined;
|
|
2575
|
+
if (this.isSandboxModeEnabled) {
|
|
2576
|
+
builderFeeRate = this.safeString2(params, 'builderFeeRate', 'defaultBuilderFeeRate');
|
|
2577
|
+
builderId = this.safeString2(params, 'builderId', 'defaultBuilderId');
|
|
2578
|
+
params = this.omit(params, ['builderFeeRate', 'defaultBuilderFeeRate', 'builderId', 'defaultBuilderId']);
|
|
2579
|
+
}
|
|
2580
|
+
else {
|
|
2581
|
+
[builderFeeRate, params] = this.handleOptionAndParams(params, 'createOrder', 'builderFeeRate', '0.0001');
|
|
2582
|
+
[builderId, params] = this.handleOptionAndParams(params, 'createOrder', 'builderId');
|
|
2583
|
+
}
|
|
2584
|
+
let totalFee = fee;
|
|
2585
|
+
if (builderFeeRate !== undefined) {
|
|
2586
|
+
totalFee = Precise["default"].stringAdd(fee, builderFeeRate);
|
|
2587
|
+
}
|
|
2588
|
+
const now = this.milliseconds();
|
|
2589
|
+
const expiryEpochMillis = this.safeInteger(params, 'expiryEpochMillis', now + 3600000);
|
|
2590
|
+
const settlementExpiration = this.safeInteger(params, 'settlementExpiration', this.parseToInt((expiryEpochMillis + 999) / 1000) + 1209600);
|
|
2591
|
+
const nonce = this.numberToString(this.nonce());
|
|
2592
|
+
const account = await this.fetchExtendedAccount();
|
|
2593
|
+
const starkKey = this.safeString(account, 'l2Key');
|
|
2594
|
+
const collateralPosition = this.safeString(account, 'l2Vault');
|
|
2595
|
+
const info = this.safeDict(market, 'info', {});
|
|
2596
|
+
const l2Config = this.safeDict(info, 'l2Config', {});
|
|
2597
|
+
const syntheticId = this.safeString(l2Config, 'syntheticId');
|
|
2598
|
+
const collateralId = this.safeString(l2Config, 'collateralId');
|
|
2599
|
+
const syntheticResolution = this.safeInteger(l2Config, 'syntheticResolution');
|
|
2600
|
+
const collateralResolution = this.safeInteger(l2Config, 'collateralResolution');
|
|
2601
|
+
if ((syntheticId === undefined) || (collateralId === undefined) || (syntheticResolution === undefined) || (collateralResolution === undefined)) {
|
|
2602
|
+
throw new errors.BadRequest(this.id + ' createOrder() requires l2Config in market info');
|
|
2603
|
+
}
|
|
2604
|
+
const settlementParams = {
|
|
2605
|
+
'totalFee': totalFee,
|
|
2606
|
+
'starkKey': starkKey,
|
|
2607
|
+
'syntheticId': syntheticId,
|
|
2608
|
+
'syntheticResolution': syntheticResolution,
|
|
2609
|
+
'collateralId': collateralId,
|
|
2610
|
+
'collateralResolution': collateralResolution,
|
|
2611
|
+
'settlementExpiration': settlementExpiration,
|
|
2612
|
+
'nonce': nonce,
|
|
2613
|
+
'collateralPosition': collateralPosition,
|
|
2614
|
+
};
|
|
2615
|
+
const isBuy = (uppercaseSide === 'BUY');
|
|
2616
|
+
const clientOrderId = this.safeString2(params, 'clientOrderId', 'client_id', this.uuid());
|
|
2617
|
+
const request = {
|
|
2618
|
+
'id': clientOrderId,
|
|
2619
|
+
'market': market['id'],
|
|
2620
|
+
'type': uppercaseType,
|
|
2621
|
+
'side': uppercaseSide,
|
|
2622
|
+
'qty': amountString,
|
|
2623
|
+
'price': priceString,
|
|
2624
|
+
'timeInForce': timeInForce,
|
|
2625
|
+
'expiryEpochMillis': expiryEpochMillis,
|
|
2626
|
+
'fee': fee,
|
|
2627
|
+
'nonce': nonce,
|
|
2628
|
+
'postOnly': postOnly,
|
|
2629
|
+
'reduceOnly': reduceOnly,
|
|
2630
|
+
'selfTradeProtectionLevel': 'ACCOUNT',
|
|
2631
|
+
};
|
|
2632
|
+
if (builderFeeRate !== undefined) {
|
|
2633
|
+
request['builderFee'] = builderFeeRate;
|
|
2634
|
+
}
|
|
2635
|
+
if (builderId !== undefined) {
|
|
2636
|
+
request['builderId'] = builderId;
|
|
2637
|
+
}
|
|
2638
|
+
const cancelId = this.safeString2(params, 'cancelId', 'previousOrderId');
|
|
2639
|
+
if (cancelId !== undefined) {
|
|
2640
|
+
request['cancelId'] = cancelId;
|
|
2641
|
+
}
|
|
2642
|
+
const settlement = this.createOrderSettlementData(isBuy, amountString, priceString, settlementParams);
|
|
2643
|
+
request['settlement'] = {
|
|
2644
|
+
'signature': { 'r': settlement['r'], 's': settlement['s'] },
|
|
2645
|
+
'starkKey': starkKey,
|
|
2646
|
+
'collateralPosition': collateralPosition,
|
|
2647
|
+
};
|
|
2648
|
+
let triggerPriceStr = this.safeString2(params, 'triggerPrice', 'stopPrice');
|
|
2649
|
+
const stopLossTriggerPrice = this.safeString(params, 'stopLossPrice');
|
|
2650
|
+
const takeProfitTriggerPrice = this.safeString(params, 'takeProfitPrice');
|
|
2651
|
+
const isStopLossOrder = stopLossTriggerPrice !== undefined;
|
|
2652
|
+
const isTakeProfitOrder = takeProfitTriggerPrice !== undefined;
|
|
2653
|
+
const stopLoss = this.safeDict(params, 'stopLoss');
|
|
2654
|
+
const takeProfit = this.safeDict(params, 'takeProfit');
|
|
2655
|
+
const hasStopLoss = (stopLoss !== undefined);
|
|
2656
|
+
const hasTakeProfit = (takeProfit !== undefined);
|
|
2657
|
+
if (hasStopLoss || hasTakeProfit) {
|
|
2658
|
+
request['tpSlType'] = 'ORDER';
|
|
2659
|
+
if (hasStopLoss) {
|
|
2660
|
+
const stopLossTrigger = this.safeString(stopLoss, 'triggerPrice');
|
|
2661
|
+
const stopLossTriggerPriceType = this.safeString(stopLoss, 'triggerPriceType');
|
|
2662
|
+
const stopLossExecutionPrice = this.safeString(stopLoss, 'price');
|
|
2663
|
+
const stopLossType = this.safeString(stopLoss, 'type');
|
|
2664
|
+
const stopLossSettlement = this.createOrderSettlementData(!isBuy, amountString, stopLossExecutionPrice, settlementParams);
|
|
2665
|
+
const requestStopLoss = {
|
|
2666
|
+
'triggerPrice': this.priceToPrecision(symbol, stopLossTrigger),
|
|
2667
|
+
'price': this.priceToPrecision(symbol, stopLossExecutionPrice),
|
|
2668
|
+
'settlement': {
|
|
2669
|
+
'signature': { 'r': stopLossSettlement['r'], 's': stopLossSettlement['s'] },
|
|
2670
|
+
'starkKey': starkKey,
|
|
2671
|
+
'collateralPosition': collateralPosition,
|
|
2672
|
+
},
|
|
2673
|
+
};
|
|
2674
|
+
if (stopLossTriggerPriceType !== undefined) {
|
|
2675
|
+
requestStopLoss['triggerPriceType'] = stopLossTriggerPriceType;
|
|
2676
|
+
}
|
|
2677
|
+
if (stopLossType !== undefined) {
|
|
2678
|
+
requestStopLoss['priceType'] = stopLossType;
|
|
2679
|
+
}
|
|
2680
|
+
request['stopLoss'] = requestStopLoss;
|
|
2681
|
+
}
|
|
2682
|
+
if (hasTakeProfit) {
|
|
2683
|
+
const takeProfitTrigger = this.safeString(takeProfit, 'triggerPrice');
|
|
2684
|
+
const takeProfitTriggerPriceType = this.safeString(takeProfit, 'triggerPriceType');
|
|
2685
|
+
const takeProfitExecutionPrice = this.safeString(takeProfit, 'price');
|
|
2686
|
+
const takeProfitType = this.safeString(takeProfit, 'type');
|
|
2687
|
+
const takeProfitSettlement = this.createOrderSettlementData(!isBuy, amountString, takeProfitExecutionPrice, settlementParams);
|
|
2688
|
+
const requestTakeProfit = {
|
|
2689
|
+
'triggerPrice': this.priceToPrecision(symbol, takeProfitTrigger),
|
|
2690
|
+
'price': this.priceToPrecision(symbol, takeProfitExecutionPrice),
|
|
2691
|
+
'settlement': {
|
|
2692
|
+
'signature': { 'r': takeProfitSettlement['r'], 's': takeProfitSettlement['s'] },
|
|
2693
|
+
'starkKey': starkKey,
|
|
2694
|
+
'collateralPosition': collateralPosition,
|
|
2695
|
+
},
|
|
2696
|
+
};
|
|
2697
|
+
if (takeProfitTriggerPriceType !== undefined) {
|
|
2698
|
+
requestTakeProfit['triggerPriceType'] = takeProfitTriggerPriceType;
|
|
2699
|
+
}
|
|
2700
|
+
if (takeProfitType !== undefined) {
|
|
2701
|
+
requestTakeProfit['priceType'] = takeProfitType;
|
|
2702
|
+
}
|
|
2703
|
+
request['takeProfit'] = requestTakeProfit;
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
else {
|
|
2707
|
+
if (triggerPriceStr !== undefined) {
|
|
2708
|
+
const triggerDirection = this.safeStringUpper(params, 'triggerDirection');
|
|
2709
|
+
if (triggerDirection === undefined) {
|
|
2710
|
+
throw new errors.ArgumentsRequired(this.id + ' createOrder() requires triggerDirection for trigger order');
|
|
2711
|
+
}
|
|
2712
|
+
const trigger = {
|
|
2713
|
+
'triggerPrice': this.priceToPrecision(symbol, triggerPriceStr),
|
|
2714
|
+
};
|
|
2715
|
+
trigger['direction'] = triggerDirection;
|
|
2716
|
+
request['type'] = 'CONDITIONAL';
|
|
2717
|
+
request['trigger'] = trigger;
|
|
2718
|
+
}
|
|
2719
|
+
else if (isStopLossOrder || isTakeProfitOrder) {
|
|
2720
|
+
triggerPriceStr = isStopLossOrder ? stopLossTriggerPrice : takeProfitTriggerPrice;
|
|
2721
|
+
const trigger = {
|
|
2722
|
+
'triggerPrice': this.priceToPrecision(symbol, triggerPriceStr),
|
|
2723
|
+
};
|
|
2724
|
+
if (isBuy) {
|
|
2725
|
+
trigger['direction'] = isStopLossOrder ? 'UP' : 'DOWN';
|
|
2726
|
+
}
|
|
2727
|
+
else {
|
|
2728
|
+
trigger['direction'] = isStopLossOrder ? 'DOWN' : 'UP';
|
|
2729
|
+
}
|
|
2730
|
+
request['type'] = 'CONDITIONAL';
|
|
2731
|
+
request['trigger'] = trigger;
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
params = this.omit(params, ['clientOrderId', 'client_id', 'timeInForce', 'postOnly', 'reduceOnly', 'reduce_only', 'fee', 'nonce', 'expiryEpochMillis', 'settlementExpiration', 'cancelId', 'previousOrderId', 'brokerId', 'referralCode', 'triggerPrice', 'stopPrice', 'triggerDirection', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit']);
|
|
2735
|
+
return {
|
|
2736
|
+
'request': this.extend(request, params),
|
|
2737
|
+
'market': market,
|
|
2738
|
+
'timestamp': now,
|
|
2739
|
+
'clientOrderId': clientOrderId,
|
|
2740
|
+
'price': priceString,
|
|
2741
|
+
'amount': amountString,
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* @method
|
|
2746
|
+
* @name extended#createOrder
|
|
2747
|
+
* @description create a trade order
|
|
2748
|
+
* @see https://api.docs.extended.exchange/#create-or-edit-order
|
|
2749
|
+
* @param {string} symbol unified symbol of the market to create an order in
|
|
2750
|
+
* @param {string} type 'limit' or 'market'
|
|
2751
|
+
* @param {string} side 'buy' or 'sell'
|
|
2752
|
+
* @param {float} amount how much of currency you want to trade in units of base currency
|
|
2753
|
+
* @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, required for all order types
|
|
2754
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2755
|
+
* @param {string} [params.clientOrderId] client order id, sent as the exchange order id
|
|
2756
|
+
* @param {string} [params.cancelId] previous external order id to replace
|
|
2757
|
+
* @param {string} [params.timeInForce] 'GTT' or 'IOC'
|
|
2758
|
+
* @param {boolean} [params.postOnly] true if the order should only make liquidity
|
|
2759
|
+
* @param {boolean} [params.reduceOnly] true if the order should only reduce a position
|
|
2760
|
+
* @param {string} [params.fee] max fee rate for the order, default is 0.0005
|
|
2761
|
+
* @param {int} [params.expiryEpochMillis] order expiration timestamp in milliseconds, default is now + 1 hour
|
|
2762
|
+
* @param {float} [params.triggerPrice] *swap only* The price at which a trigger order is triggered at
|
|
2763
|
+
* @param {float} [params.stopLossPrice] *swap only* The price at which a stop loss order is triggered at
|
|
2764
|
+
* @param {float} [params.takeProfitPrice] *swap only* The price at which a take profit order is triggered at
|
|
2765
|
+
* @param {object} [params.takeProfit] *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered (perpetual swap markets only)
|
|
2766
|
+
* @param {float} [params.takeProfit.triggerPrice] *swap only* take profit trigger price
|
|
2767
|
+
* @param {float} [params.takeProfit.price] *swap only* the execution price for a take profit attached to a trigger order
|
|
2768
|
+
* @param {string} [params.takeProfit.type] *swap only* the type for a take profit attached to a trigger order, 'LAST', 'MARK' or 'INDEX', default is ''
|
|
2769
|
+
* @param {object} [params.stopLoss] *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only)
|
|
2770
|
+
* @param {float} [params.stopLoss.triggerPrice] *swap only* stop loss trigger price
|
|
2771
|
+
* @param {float} [params.stopLoss.price] *swap only* the execution price for a stop loss attached to a trigger order
|
|
2772
|
+
* @param {string} [params.stopLoss.type] *swap only* the type for a stop loss attached to a trigger order, 'LAST', 'MARK' or 'INDEX', default is ''
|
|
2773
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
2774
|
+
*/
|
|
2775
|
+
async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
|
|
2776
|
+
this.checkRequiredCredentials();
|
|
2777
|
+
const extendedOrderRequest = await this.createExtendedOrderRequest(symbol, type, side, amount, price, params);
|
|
2778
|
+
const request = this.safeDict(extendedOrderRequest, 'request', {});
|
|
2779
|
+
const response = await this.v1PrivatePostUserOrder(request);
|
|
2780
|
+
//
|
|
2781
|
+
// {
|
|
2782
|
+
// "status": "OK",
|
|
2783
|
+
// "data": {
|
|
2784
|
+
// "id": "2051479786538188800",
|
|
2785
|
+
// "externalId": "3480985089570526249141260266819446928410958787024864860785196119336740291620"
|
|
2786
|
+
// }
|
|
2787
|
+
// }
|
|
2788
|
+
//
|
|
2789
|
+
const data = this.safeDict(response, 'data', {});
|
|
2790
|
+
const market = extendedOrderRequest['market'];
|
|
2791
|
+
const now = this.safeInteger(extendedOrderRequest, 'timestamp');
|
|
2792
|
+
data['timestamp'] = now;
|
|
2793
|
+
data['status'] = 'NEW';
|
|
2794
|
+
return this.parseOrder(this.extend(request, data), market);
|
|
2795
|
+
}
|
|
2796
|
+
/**
|
|
2797
|
+
* @method
|
|
2798
|
+
* @name extended#editOrder
|
|
2799
|
+
* @description edit a trade order
|
|
2800
|
+
* @see https://api.docs.extended.exchange/#create-or-edit-order
|
|
2801
|
+
* @param {string} id order id assigned by Extended
|
|
2802
|
+
* @param {string} symbol unified symbol of the market to edit an order in
|
|
2803
|
+
* @param {string} type 'limit' or 'market'
|
|
2804
|
+
* @param {string} side 'buy' or 'sell'
|
|
2805
|
+
* @param {float} [amount] how much of currency you want to trade in units of base currency
|
|
2806
|
+
* @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency
|
|
2807
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2808
|
+
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
2809
|
+
*/
|
|
2810
|
+
async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
|
|
2811
|
+
if (id === undefined) {
|
|
2812
|
+
throw new errors.ArgumentsRequired(this.id + ' editOrder() requires an id argument');
|
|
2813
|
+
}
|
|
2814
|
+
let expiryEpochMillis = this.safeInteger(params, 'expiryEpochMillis');
|
|
2815
|
+
let postOnly = this.safeBool(params, 'postOnly');
|
|
2816
|
+
let reduceOnly = this.safeBool2(params, 'reduceOnly', 'reduce_only');
|
|
2817
|
+
let cancelId = this.safeString2(params, 'cancelId', 'previousOrderId');
|
|
2818
|
+
if ((amount === undefined) || (price === undefined) || (expiryEpochMillis === undefined) || (postOnly === undefined) || (reduceOnly === undefined) || (cancelId === undefined)) {
|
|
2819
|
+
const response = await this.v1PrivateGetUserOrdersId({ 'id': id });
|
|
2820
|
+
const order = this.safeDict(response, 'data', {});
|
|
2821
|
+
if (amount === undefined) {
|
|
2822
|
+
amount = this.safeNumber(order, 'qty');
|
|
2823
|
+
}
|
|
2824
|
+
if (price === undefined) {
|
|
2825
|
+
price = this.safeNumber(order, 'price');
|
|
2826
|
+
}
|
|
2827
|
+
if (expiryEpochMillis === undefined) {
|
|
2828
|
+
expiryEpochMillis = this.safeInteger(order, 'expireTime');
|
|
2829
|
+
}
|
|
2830
|
+
if (postOnly === undefined) {
|
|
2831
|
+
postOnly = this.safeBool(order, 'postOnly', false);
|
|
2832
|
+
}
|
|
2833
|
+
if (reduceOnly === undefined) {
|
|
2834
|
+
reduceOnly = this.safeBool(order, 'reduceOnly', false);
|
|
2835
|
+
}
|
|
2836
|
+
if (cancelId === undefined) {
|
|
2837
|
+
cancelId = this.safeString(order, 'externalId');
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
if (amount === undefined) {
|
|
2841
|
+
throw new errors.ArgumentsRequired(this.id + ' editOrder() requires an amount argument or an existing order with qty');
|
|
2842
|
+
}
|
|
2843
|
+
if (price === undefined) {
|
|
2844
|
+
throw new errors.ArgumentsRequired(this.id + ' editOrder() requires a price argument or an existing order with price');
|
|
2845
|
+
}
|
|
2846
|
+
params = this.extend({
|
|
2847
|
+
'postOnly': postOnly,
|
|
2848
|
+
'reduceOnly': reduceOnly,
|
|
2849
|
+
}, params);
|
|
2850
|
+
const requestParams = this.extend(params, {
|
|
2851
|
+
'cancelId': cancelId,
|
|
2852
|
+
'expiryEpochMillis': expiryEpochMillis,
|
|
2853
|
+
});
|
|
2854
|
+
const extendedOrderRequest = await this.createExtendedOrderRequest(symbol, type, side, amount, price, requestParams);
|
|
2855
|
+
const request = this.safeDict(extendedOrderRequest, 'request', {});
|
|
2856
|
+
const editResponse = await this.v1PrivatePostUserOrder(request);
|
|
2857
|
+
//
|
|
2858
|
+
// {
|
|
2859
|
+
// "status": "OK",
|
|
2860
|
+
// "data": {
|
|
2861
|
+
// "id": "2051479786538188800",
|
|
2862
|
+
// "externalId": "3480985089570526249141260266819446928410958787024864860785196119336740291620"
|
|
2863
|
+
// }
|
|
2864
|
+
// }
|
|
2865
|
+
//
|
|
2866
|
+
const responseData = this.safeDict(editResponse, 'data', {});
|
|
2867
|
+
const market = extendedOrderRequest['market'];
|
|
2868
|
+
const now = this.safeInteger(extendedOrderRequest, 'timestamp');
|
|
2869
|
+
responseData['timestamp'] = now;
|
|
2870
|
+
responseData['status'] = 'NEW';
|
|
2871
|
+
return this.parseOrder(this.extend(request, responseData), market);
|
|
2872
|
+
}
|
|
2873
|
+
/**
|
|
2874
|
+
* @method
|
|
2875
|
+
* @name extended#cancelOrder
|
|
2876
|
+
* @description cancels an open order
|
|
2877
|
+
* @see https://api.docs.extended.exchange/#cancel-order-by-id
|
|
2878
|
+
* @see https://api.docs.extended.exchange/#cancel-order-by-external-id
|
|
2879
|
+
* @param {string} id order id assigned by Extended
|
|
2880
|
+
* @param {string} [symbol] unified symbol of the market the order was made in
|
|
2881
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2882
|
+
* @param {string} [params.clientOrderId] user-defined order id, cancels by external id
|
|
2883
|
+
* @returns {object} An [order structure]{@link https://docs.ccxt.com/?id=order-structure}
|
|
2884
|
+
*/
|
|
2885
|
+
async cancelOrder(id, symbol = undefined, params = {}) {
|
|
2886
|
+
await this.loadMarkets();
|
|
2887
|
+
let market = undefined;
|
|
2888
|
+
if (symbol !== undefined) {
|
|
2889
|
+
market = this.market(symbol);
|
|
2890
|
+
}
|
|
2891
|
+
let response = undefined;
|
|
2892
|
+
const clientOrderId = this.safeString2(params, 'clientOrderId', 'client_id');
|
|
2893
|
+
params = this.omit(params, ['clientOrderId', 'client_id']);
|
|
2894
|
+
if (clientOrderId !== undefined) {
|
|
2895
|
+
const request = {
|
|
2896
|
+
'externalId': clientOrderId,
|
|
2897
|
+
};
|
|
2898
|
+
response = await this.v1PrivateDeleteUserOrder(this.extend(request, params));
|
|
2899
|
+
}
|
|
2900
|
+
else {
|
|
2901
|
+
if (id === undefined) {
|
|
2902
|
+
throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires an id argument');
|
|
2903
|
+
}
|
|
2904
|
+
const request = {
|
|
2905
|
+
'id': id,
|
|
2906
|
+
};
|
|
2907
|
+
response = await this.v1PrivateDeleteUserOrderId(this.extend(request, params));
|
|
2908
|
+
}
|
|
2909
|
+
//
|
|
2910
|
+
// {
|
|
2911
|
+
// "status": "OK"
|
|
2912
|
+
// }
|
|
2913
|
+
//
|
|
2914
|
+
const orderId = (clientOrderId === undefined) ? id : undefined;
|
|
2915
|
+
const orderSymbol = (market === undefined) ? symbol : market['symbol'];
|
|
2916
|
+
return this.safeOrder({
|
|
2917
|
+
'info': response,
|
|
2918
|
+
'id': orderId,
|
|
2919
|
+
'clientOrderId': clientOrderId,
|
|
2920
|
+
'timestamp': undefined,
|
|
2921
|
+
'datetime': undefined,
|
|
2922
|
+
'symbol': orderSymbol,
|
|
2923
|
+
'status': 'canceled',
|
|
2924
|
+
}, market);
|
|
2925
|
+
}
|
|
2926
|
+
/**
|
|
2927
|
+
* @method
|
|
2928
|
+
* @name extended#cancelOrders
|
|
2929
|
+
* @description cancel multiple orders by order ids or client order ids
|
|
2930
|
+
* @see https://api.docs.extended.exchange/#mass-cancel
|
|
2931
|
+
* @param {string[]} ids order ids
|
|
2932
|
+
* @param {string} [symbol] unified market symbol, only used to populate the returned orders
|
|
2933
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2934
|
+
* @param {string[]} [params.clientOrderIds] client order ids
|
|
2935
|
+
* @param {string} [params.clientOrderId] single client order id
|
|
2936
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
|
|
2937
|
+
*/
|
|
2938
|
+
async cancelOrders(ids, symbol = undefined, params = {}) {
|
|
2939
|
+
await this.loadMarkets();
|
|
2940
|
+
let clientOrderIds = this.safeListN(params, ['clientOrderIds', 'client_order_ids', 'externalOrderIds', 'external_order_ids']);
|
|
2941
|
+
const clientOrderId = this.safeString2(params, 'clientOrderId', 'client_id');
|
|
2942
|
+
params = this.omit(params, ['clientOrderIds', 'client_order_ids', 'clientOrderId', 'client_id', 'externalOrderIds', 'external_order_ids', 'orderIds', 'order_ids', 'markets', 'cancelAll', 'cancel_all']);
|
|
2943
|
+
const request = {};
|
|
2944
|
+
const hasOrderIds = ids !== undefined;
|
|
2945
|
+
if (hasOrderIds) {
|
|
2946
|
+
const idsLength = ids.length;
|
|
2947
|
+
if (idsLength > 0) {
|
|
2948
|
+
request['orderIds'] = ids;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
if (clientOrderIds === undefined && clientOrderId !== undefined) {
|
|
2952
|
+
clientOrderIds = [clientOrderId];
|
|
2953
|
+
}
|
|
2954
|
+
const hasClientOrderIds = clientOrderIds !== undefined;
|
|
2955
|
+
if (hasClientOrderIds) {
|
|
2956
|
+
const clientOrderIdsLength = clientOrderIds.length;
|
|
2957
|
+
if (clientOrderIdsLength > 0) {
|
|
2958
|
+
request['externalOrderIds'] = clientOrderIds;
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
if (!hasOrderIds && !hasClientOrderIds) {
|
|
2962
|
+
throw new errors.ArgumentsRequired(this.id + ' cancelOrders() requires an ids argument or clientOrderIds parameter');
|
|
2963
|
+
}
|
|
2964
|
+
await this.v1PrivatePostUserOrderMassCancel(this.extend(request, params));
|
|
2965
|
+
//
|
|
2966
|
+
// {
|
|
2967
|
+
// "status": "OK",
|
|
2968
|
+
// "data": {}
|
|
2969
|
+
// }
|
|
2970
|
+
//
|
|
2971
|
+
return [];
|
|
2972
|
+
}
|
|
2973
|
+
/**
|
|
2974
|
+
* @method
|
|
2975
|
+
* @name extended#cancelAllOrders
|
|
2976
|
+
* @description cancels all open orders, optionally filtered by symbol
|
|
2977
|
+
* @see https://api.docs.extended.exchange/#mass-cancel
|
|
2978
|
+
* @param {string} [symbol] unified market symbol of the market to cancel orders in
|
|
2979
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
2980
|
+
* @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/?id=order-structure}
|
|
2981
|
+
*/
|
|
2982
|
+
async cancelAllOrders(symbol = undefined, params = {}) {
|
|
2983
|
+
await this.loadMarkets();
|
|
2984
|
+
const request = {
|
|
2985
|
+
'cancelAll': true,
|
|
2986
|
+
};
|
|
2987
|
+
let market = undefined;
|
|
2988
|
+
if (symbol !== undefined) {
|
|
2989
|
+
market = this.market(symbol);
|
|
2990
|
+
request['markets'] = [market['id']];
|
|
2991
|
+
}
|
|
2992
|
+
await this.v1PrivatePostUserOrderMassCancel(this.extend(request, params));
|
|
2993
|
+
//
|
|
2994
|
+
// {
|
|
2995
|
+
// "status": "OK",
|
|
2996
|
+
// "data": {}
|
|
2997
|
+
// }
|
|
2998
|
+
//
|
|
2999
|
+
return [];
|
|
3000
|
+
}
|
|
3001
|
+
/**
|
|
3002
|
+
* @method
|
|
3003
|
+
* @name extended#cancelAllOrdersAfter
|
|
3004
|
+
* @description dead man's switch, cancel all orders after the given timeout
|
|
3005
|
+
* @see https://api.docs.extended.exchange/#mass-auto-cancel-dead-man-39-s-switch
|
|
3006
|
+
* @param {number} timeout time in milliseconds, 0 represents cancel the timer
|
|
3007
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
3008
|
+
* @returns {object} the api result
|
|
3009
|
+
*/
|
|
3010
|
+
async cancelAllOrdersAfter(timeout, params = {}) {
|
|
3011
|
+
await this.loadMarkets();
|
|
3012
|
+
const request = {
|
|
3013
|
+
'countdownTime': (timeout > 0) ? this.parseToInt(timeout / 1000) : 0,
|
|
3014
|
+
};
|
|
3015
|
+
return await this.v1PrivatePostUserDeadmanswitch(this.extend(request, params));
|
|
3016
|
+
}
|
|
3017
|
+
/**
|
|
3018
|
+
* @method
|
|
3019
|
+
* @name extended#fetchOrder
|
|
3020
|
+
* @description fetches information on an order made by the user
|
|
3021
|
+
* @see https://api.docs.extended.exchange/#get-order-by-id
|
|
3022
|
+
* @see https://api.docs.extended.exchange/#get-orders-by-external-id
|
|
3023
|
+
* @param {string} id order id assigned by Extended
|
|
3024
|
+
* @param {string} [symbol] unified symbol of the market the order was made in
|
|
3025
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
3026
|
+
* @param {string} [params.clientOrderId] user-defined order id, fetches by external id
|
|
3027
|
+
* @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
3028
|
+
*/
|
|
3029
|
+
async fetchOrder(id, symbol = undefined, params = {}) {
|
|
3030
|
+
await this.loadMarkets();
|
|
3031
|
+
let market = undefined;
|
|
3032
|
+
if (symbol !== undefined) {
|
|
3033
|
+
market = this.market(symbol);
|
|
3034
|
+
}
|
|
3035
|
+
let response = undefined;
|
|
3036
|
+
let order = undefined;
|
|
3037
|
+
const clientOrderId = this.safeString2(params, 'clientOrderId', 'client_id');
|
|
3038
|
+
params = this.omit(params, ['clientOrderId', 'client_id']);
|
|
3039
|
+
if (clientOrderId !== undefined) {
|
|
3040
|
+
const request = {
|
|
3041
|
+
'externalId': clientOrderId,
|
|
3042
|
+
};
|
|
3043
|
+
response = await this.v1PrivateGetUserOrdersExternalExternalId(this.extend(request, params));
|
|
3044
|
+
const data = this.safeList(response, 'data', []);
|
|
3045
|
+
order = this.safeDict(data, 0, {});
|
|
3046
|
+
}
|
|
3047
|
+
else {
|
|
3048
|
+
if (id === undefined) {
|
|
3049
|
+
throw new errors.ArgumentsRequired(this.id + ' fetchOrder() requires an id argument');
|
|
3050
|
+
}
|
|
3051
|
+
const request = {
|
|
3052
|
+
'id': id,
|
|
3053
|
+
};
|
|
3054
|
+
response = await this.v1PrivateGetUserOrdersId(this.extend(request, params));
|
|
3055
|
+
order = this.safeDict(response, 'data', {});
|
|
3056
|
+
}
|
|
3057
|
+
return this.parseOrder(order, market);
|
|
3058
|
+
}
|
|
3059
|
+
/**
|
|
3060
|
+
* @method
|
|
3061
|
+
* @name extended#fetchOpenOrders
|
|
3062
|
+
* @description fetch all unfilled currently open orders
|
|
3063
|
+
* @see https://api.docs.extended.exchange/#get-open-orders
|
|
3064
|
+
* @param {string} [symbol] unified market symbol of the orders
|
|
3065
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
3066
|
+
* @param {int} [limit] the maximum number of open order structures to retrieve
|
|
3067
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
3068
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
3069
|
+
*/
|
|
3070
|
+
async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
3071
|
+
await this.loadMarkets();
|
|
3072
|
+
let market = undefined;
|
|
3073
|
+
const request = {};
|
|
3074
|
+
if (symbol !== undefined) {
|
|
3075
|
+
market = this.market(symbol);
|
|
3076
|
+
request['market'] = market['id'];
|
|
3077
|
+
}
|
|
3078
|
+
const response = await this.v1PrivateGetUserOrders(this.extend(request, params));
|
|
3079
|
+
//
|
|
3080
|
+
// {
|
|
3081
|
+
// "status": "OK",
|
|
3082
|
+
// "data": [
|
|
3083
|
+
// {
|
|
3084
|
+
// "id": 1775511783722512384,
|
|
3085
|
+
// "accountId": 3017,
|
|
3086
|
+
// "externalId": "2554612759479898620327573136214120486511160383028978112799136270841501275076",
|
|
3087
|
+
// "market": "ETH-USD",
|
|
3088
|
+
// "type": "LIMIT",
|
|
3089
|
+
// "side": "BUY",
|
|
3090
|
+
// "status": "PARTIALLY_FILLED",
|
|
3091
|
+
// "price": "3300",
|
|
3092
|
+
// "averagePrice": "3297.00",
|
|
3093
|
+
// "qty": "0.2",
|
|
3094
|
+
// "filledQty": "0.1",
|
|
3095
|
+
// "payedFee": "0.0120000000000000",
|
|
3096
|
+
// "reduceOnly": false,
|
|
3097
|
+
// "postOnly": false,
|
|
3098
|
+
// "createdTime": 1701563440000,
|
|
3099
|
+
// "updatedTime": 1701563440000,
|
|
3100
|
+
// "timeInForce": "IOC",
|
|
3101
|
+
// "expireTime": 1712754771819
|
|
3102
|
+
// }
|
|
3103
|
+
// ]
|
|
3104
|
+
// }
|
|
3105
|
+
//
|
|
3106
|
+
const data = this.safeList(response, 'data', []);
|
|
3107
|
+
const orders = this.parseOrders(data, market, since, limit);
|
|
3108
|
+
return this.filterBySymbolSinceLimit(orders, symbol, since, limit);
|
|
3109
|
+
}
|
|
3110
|
+
/**
|
|
3111
|
+
* @method
|
|
3112
|
+
* @name extended#fetchOrders
|
|
3113
|
+
* @description fetches information on multiple orders made by the user
|
|
3114
|
+
* @see https://api.docs.extended.exchange/#get-orders-history
|
|
3115
|
+
* @param {string} [symbol] unified market symbol of the orders
|
|
3116
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
3117
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
3118
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
3119
|
+
* @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)
|
|
3120
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
3121
|
+
*/
|
|
3122
|
+
async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
3123
|
+
await this.loadMarkets();
|
|
3124
|
+
let paginate = false;
|
|
3125
|
+
[paginate, params] = this.handleOptionAndParams(params, 'fetchOrders', 'paginate');
|
|
3126
|
+
if (paginate) {
|
|
3127
|
+
return await this.fetchPaginatedCallCursor('fetchOrders', symbol, since, limit, params, 'cursor', 'cursor', undefined, 100);
|
|
3128
|
+
}
|
|
3129
|
+
let market = undefined;
|
|
3130
|
+
const request = {};
|
|
3131
|
+
if (symbol !== undefined) {
|
|
3132
|
+
market = this.market(symbol);
|
|
3133
|
+
request['market'] = market['id'];
|
|
3134
|
+
}
|
|
3135
|
+
if (limit !== undefined) {
|
|
3136
|
+
request['limit'] = limit;
|
|
3137
|
+
}
|
|
3138
|
+
const response = await this.v1PrivateGetUserOrdersHistory(this.extend(params, request));
|
|
3139
|
+
//
|
|
3140
|
+
// {
|
|
3141
|
+
// "status": "OK",
|
|
3142
|
+
// "data": [
|
|
3143
|
+
// {
|
|
3144
|
+
// "id": 1784963886257016832,
|
|
3145
|
+
// "externalId": "ExtId-1",
|
|
3146
|
+
// "accountId": 1,
|
|
3147
|
+
// "market": "BTC-USD",
|
|
3148
|
+
// "status": "FILLED",
|
|
3149
|
+
// "type": "LIMIT",
|
|
3150
|
+
// "side": "BUY",
|
|
3151
|
+
// "price": "39000",
|
|
3152
|
+
// "averagePrice": "39000",
|
|
3153
|
+
// "qty": "0.2",
|
|
3154
|
+
// "filledQty": "0.1",
|
|
3155
|
+
// "payedFee": "0.0120000000000000",
|
|
3156
|
+
// "reduceOnly": false,
|
|
3157
|
+
// "postOnly": false,
|
|
3158
|
+
// "createdTime": 1701563440000,
|
|
3159
|
+
// "updatedTime": 1701563440000,
|
|
3160
|
+
// "timeInForce": "IOC",
|
|
3161
|
+
// "expireTime": 1706563440
|
|
3162
|
+
// }
|
|
3163
|
+
// ],
|
|
3164
|
+
// "pagination": {
|
|
3165
|
+
// "cursor": 1784963886257016832,
|
|
3166
|
+
// "count": 1
|
|
3167
|
+
// }
|
|
3168
|
+
// }
|
|
3169
|
+
//
|
|
3170
|
+
const data = this.safeList(response, 'data', []);
|
|
3171
|
+
const pagination = this.safeDict(response, 'pagination', {});
|
|
3172
|
+
const cursor = this.safeString(pagination, 'cursor');
|
|
3173
|
+
const result = [];
|
|
3174
|
+
const dataLength = data.length;
|
|
3175
|
+
for (let i = 0; i < dataLength; i++) {
|
|
3176
|
+
let entry = data[i];
|
|
3177
|
+
if ((cursor !== undefined) && (i === dataLength - 1)) {
|
|
3178
|
+
entry = this.extend(entry, { 'cursor': cursor });
|
|
3179
|
+
}
|
|
3180
|
+
result.push(entry);
|
|
3181
|
+
}
|
|
3182
|
+
const orders = this.parseOrders(result, market, since, limit);
|
|
3183
|
+
return this.filterBySymbolSinceLimit(orders, symbol, since, limit);
|
|
3184
|
+
}
|
|
3185
|
+
/**
|
|
3186
|
+
* @method
|
|
3187
|
+
* @name extended#fetchClosedOrders
|
|
3188
|
+
* @description fetches information on multiple closed orders made by the user
|
|
3189
|
+
* @see https://api.docs.extended.exchange/#get-orders-history
|
|
3190
|
+
* @param {string} [symbol] unified market symbol of the orders
|
|
3191
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
3192
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
3193
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
3194
|
+
* @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)
|
|
3195
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
3196
|
+
*/
|
|
3197
|
+
async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
3198
|
+
const orders = await this.fetchOrders(symbol, since, undefined, params);
|
|
3199
|
+
const closedOrders = this.filterBy(orders, 'status', 'closed');
|
|
3200
|
+
return this.filterBySymbolSinceLimit(closedOrders, symbol, since, limit);
|
|
3201
|
+
}
|
|
3202
|
+
/**
|
|
3203
|
+
* @method
|
|
3204
|
+
* @name extended#fetchCanceledOrders
|
|
3205
|
+
* @description fetches information on multiple canceled orders made by the user
|
|
3206
|
+
* @see https://api.docs.extended.exchange/#get-orders-history
|
|
3207
|
+
* @param {string} [symbol] unified market symbol of the orders
|
|
3208
|
+
* @param {int} [since] the earliest time in ms to fetch orders for
|
|
3209
|
+
* @param {int} [limit] the maximum number of order structures to retrieve
|
|
3210
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
3211
|
+
* @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)
|
|
3212
|
+
* @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
3213
|
+
*/
|
|
3214
|
+
async fetchCanceledOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
|
3215
|
+
const orders = await this.fetchOrders(symbol, since, undefined, params);
|
|
3216
|
+
const canceledOrders = this.filterBy(orders, 'status', 'canceled');
|
|
3217
|
+
return this.filterBySymbolSinceLimit(canceledOrders, symbol, since, limit);
|
|
3218
|
+
}
|
|
3219
|
+
parseOrderStatus(status) {
|
|
3220
|
+
const statuses = {
|
|
3221
|
+
'NEW': 'open',
|
|
3222
|
+
'PARTIALLY_FILLED': 'open',
|
|
3223
|
+
'UNTRIGGERED': 'open',
|
|
3224
|
+
'TRIGGERED': 'open',
|
|
3225
|
+
'FILLED': 'closed',
|
|
3226
|
+
'CANCELLED': 'canceled',
|
|
3227
|
+
'REJECTED': 'rejected',
|
|
3228
|
+
'EXPIRED': 'expired',
|
|
3229
|
+
};
|
|
3230
|
+
return this.safeString(statuses, status, status);
|
|
3231
|
+
}
|
|
3232
|
+
parseOrder(order, market = undefined) {
|
|
3233
|
+
//
|
|
3234
|
+
// {
|
|
3235
|
+
// "id": 1784963886257016832,
|
|
3236
|
+
// "externalId": "ExtId-1",
|
|
3237
|
+
// "accountId": 1,
|
|
3238
|
+
// "market": "BTC-USD",
|
|
3239
|
+
// "status": "FILLED",
|
|
3240
|
+
// "type": "LIMIT",
|
|
3241
|
+
// "side": "BUY",
|
|
3242
|
+
// "price": "39000",
|
|
3243
|
+
// "averagePrice": "39000",
|
|
3244
|
+
// "qty": "0.2",
|
|
3245
|
+
// "filledQty": "0.1",
|
|
3246
|
+
// "payedFee": "0.0120000000000000",
|
|
3247
|
+
// "reduceOnly": false,
|
|
3248
|
+
// "postOnly": false,
|
|
3249
|
+
// "trigger": {
|
|
3250
|
+
// "triggerPrice": "34000",
|
|
3251
|
+
// "triggerPriceType": "LAST",
|
|
3252
|
+
// "triggerPriceDirection": "UP",
|
|
3253
|
+
// "executionPriceType": "MARKET"
|
|
3254
|
+
// },
|
|
3255
|
+
// "takeProfit": {
|
|
3256
|
+
// "triggerPrice": "34000",
|
|
3257
|
+
// "triggerPriceType": "LAST",
|
|
3258
|
+
// "price": "35000",
|
|
3259
|
+
// "priceType": "MARKET"
|
|
3260
|
+
// },
|
|
3261
|
+
// "stopLoss": {
|
|
3262
|
+
// "triggerPrice": "34000",
|
|
3263
|
+
// "triggerPriceType": "LAST",
|
|
3264
|
+
// "price": "35000",
|
|
3265
|
+
// "priceType": "MARKET"
|
|
3266
|
+
// },
|
|
3267
|
+
// "createdTime": 1701563440000,
|
|
3268
|
+
// "updatedTime": 1701563440000,
|
|
3269
|
+
// "timeInForce": "IOC",
|
|
3270
|
+
// "expireTime": 1706563440
|
|
3271
|
+
// }
|
|
3272
|
+
//
|
|
3273
|
+
const marketId = this.safeString(order, 'market');
|
|
3274
|
+
market = this.safeMarket(marketId, market);
|
|
3275
|
+
const timestamp = this.safeInteger2(order, 'createdTime', 'timestamp');
|
|
3276
|
+
const lastUpdateTimestamp = this.safeInteger(order, 'updatedTime');
|
|
3277
|
+
const status = this.parseOrderStatus(this.safeString(order, 'status'));
|
|
3278
|
+
const side = this.safeStringLower(order, 'side');
|
|
3279
|
+
const type = this.safeStringLower(order, 'type');
|
|
3280
|
+
const amount = this.safeString(order, 'qty');
|
|
3281
|
+
const filled = this.safeString(order, 'filledQty');
|
|
3282
|
+
const feeCost = this.safeString(order, 'payedFee');
|
|
3283
|
+
const trigger = this.safeDict(order, 'trigger', {});
|
|
3284
|
+
const takeProfit = this.safeDict(order, 'takeProfit', {});
|
|
3285
|
+
const stopLoss = this.safeDict(order, 'stopLoss', {});
|
|
3286
|
+
const fee = {
|
|
3287
|
+
'cost': feeCost,
|
|
3288
|
+
'currency': (market === undefined) ? undefined : market['settle'],
|
|
3289
|
+
};
|
|
3290
|
+
return this.safeOrder({
|
|
3291
|
+
'info': order,
|
|
3292
|
+
'id': this.safeString(order, 'id'),
|
|
3293
|
+
'clientOrderId': this.safeString(order, 'externalId'),
|
|
3294
|
+
'timestamp': timestamp,
|
|
3295
|
+
'datetime': this.iso8601(timestamp),
|
|
3296
|
+
'lastTradeTimestamp': undefined,
|
|
3297
|
+
'lastUpdateTimestamp': lastUpdateTimestamp,
|
|
3298
|
+
'symbol': market['symbol'],
|
|
3299
|
+
'type': type,
|
|
3300
|
+
'timeInForce': this.safeString(order, 'timeInForce'),
|
|
3301
|
+
'postOnly': this.safeBool(order, 'postOnly'),
|
|
3302
|
+
'reduceOnly': this.safeBool(order, 'reduceOnly'),
|
|
3303
|
+
'side': side,
|
|
3304
|
+
'price': this.safeString(order, 'price'),
|
|
3305
|
+
'triggerPrice': this.safeString(trigger, 'triggerPrice'),
|
|
3306
|
+
'takeProfitPrice': this.safeString(takeProfit, 'triggerPrice'),
|
|
3307
|
+
'stopLossPrice': this.safeString(stopLoss, 'triggerPrice'),
|
|
3308
|
+
'amount': amount,
|
|
3309
|
+
'cost': undefined,
|
|
3310
|
+
'average': this.safeString(order, 'averagePrice'),
|
|
3311
|
+
'filled': filled,
|
|
3312
|
+
'remaining': undefined,
|
|
3313
|
+
'status': status,
|
|
3314
|
+
'fee': fee,
|
|
3315
|
+
'trades': undefined,
|
|
3316
|
+
}, market);
|
|
3317
|
+
}
|
|
3318
|
+
getExtendedStringToFelt(value) {
|
|
3319
|
+
return this.convertToBigInt(this.stringToBase16(value));
|
|
3320
|
+
}
|
|
3321
|
+
getExtendedEncodeI64(value) {
|
|
3322
|
+
// Cairo prime offset for i64 negative encoding.
|
|
3323
|
+
const prime = '3618502788666131213697322783095070105623107215331596699973092056135872020481';
|
|
3324
|
+
const valueString = this.numberToString(value);
|
|
3325
|
+
if (Precise["default"].stringLt(valueString, '0')) {
|
|
3326
|
+
return Precise["default"].stringAdd(prime, valueString);
|
|
3327
|
+
}
|
|
3328
|
+
return value;
|
|
3329
|
+
}
|
|
3330
|
+
getExtendedDecimalToBase16(value) {
|
|
3331
|
+
let decimalString = '';
|
|
3332
|
+
if (typeof value === 'string') {
|
|
3333
|
+
decimalString = value;
|
|
3334
|
+
}
|
|
3335
|
+
else {
|
|
3336
|
+
decimalString = this.numberToString(value);
|
|
3337
|
+
}
|
|
3338
|
+
const hexChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
|
3339
|
+
let result = '';
|
|
3340
|
+
while (Precise["default"].stringGt(decimalString, '0')) {
|
|
3341
|
+
const remainder = this.parseToInt(Precise["default"].stringMod(decimalString, '16'));
|
|
3342
|
+
result = hexChars[remainder] + result;
|
|
3343
|
+
decimalString = Precise["default"].stringDiv(decimalString, '16', 0);
|
|
3344
|
+
}
|
|
3345
|
+
if (result === '') {
|
|
3346
|
+
return '0';
|
|
3347
|
+
}
|
|
3348
|
+
return result;
|
|
3349
|
+
}
|
|
3350
|
+
getExtendedSignatureHex(signature) {
|
|
3351
|
+
if (typeof signature === 'string') {
|
|
3352
|
+
if (signature.indexOf('0x') === 0) {
|
|
3353
|
+
return signature;
|
|
3354
|
+
}
|
|
3355
|
+
return '0x' + this.getExtendedDecimalToBase16(signature);
|
|
3356
|
+
}
|
|
3357
|
+
const signatureString = this.numberToString(signature);
|
|
3358
|
+
if (signatureString.indexOf('0x') === 0) {
|
|
3359
|
+
return signatureString;
|
|
3360
|
+
}
|
|
3361
|
+
return '0x' + this.getExtendedDecimalToBase16(signatureString);
|
|
3362
|
+
}
|
|
3363
|
+
getExtendedDomainHash() {
|
|
3364
|
+
const domainTypeHash = this.convertToBigInt(this.extendedStarknetGetSelectorFromName('"StarknetDomain"("name":"shortstring","version":"shortstring","chainId":"shortstring","revision":"shortstring")'));
|
|
3365
|
+
const isTestnet = this.urls['api']['rest'].indexOf('sepolia') >= 0;
|
|
3366
|
+
const defaultChainId = isTestnet ? 'SN_SEPOLIA' : 'SN_MAIN';
|
|
3367
|
+
const chainId = this.safeString(this.options, 'chainId', defaultChainId);
|
|
3368
|
+
return this.convertToBigInt(this.extendedStarknetComputePoseidonHashOnElements([
|
|
3369
|
+
domainTypeHash,
|
|
3370
|
+
this.getExtendedStringToFelt('Perpetuals'),
|
|
3371
|
+
this.getExtendedStringToFelt('v0'),
|
|
3372
|
+
this.getExtendedStringToFelt(chainId),
|
|
3373
|
+
this.convertToBigInt('1'),
|
|
3374
|
+
]));
|
|
3375
|
+
}
|
|
3376
|
+
getExtendedOrderMsgHash(settlement) {
|
|
3377
|
+
const orderTypeHash = this.convertToBigInt(this.extendedStarknetGetSelectorFromName('"Order"("position_id":"felt","base_asset_id":"AssetId","base_amount":"i64","quote_asset_id":"AssetId","quote_amount":"i64","fee_asset_id":"AssetId","fee_amount":"u64","expiration":"Timestamp","salt":"felt")"PositionId"("value":"u32")"AssetId"("value":"felt")"Timestamp"("seconds":"u64")'));
|
|
3378
|
+
const domainHash = this.getExtendedDomainHash();
|
|
3379
|
+
// Order fields
|
|
3380
|
+
const positionId = this.convertToBigInt(this.safeString(settlement, 'collateralPosition'));
|
|
3381
|
+
const baseAssetId = this.safeString(settlement, 'baseAssetId');
|
|
3382
|
+
const baseAmount = this.convertToBigInt(this.safeString(settlement, 'baseAmount'));
|
|
3383
|
+
const quoteAssetId = this.safeString(settlement, 'quoteAssetId');
|
|
3384
|
+
const quoteAmount = this.convertToBigInt(this.safeString(settlement, 'quoteAmount'));
|
|
3385
|
+
const feeAssetId = this.safeString(settlement, 'feeAssetId');
|
|
3386
|
+
const feeAmount = this.convertToBigInt(this.safeString(settlement, 'feeAmount'));
|
|
3387
|
+
const expiration = this.convertToBigInt(this.safeString2(settlement, 'expiration', 'expirationTimestamp'));
|
|
3388
|
+
const salt = this.convertToBigInt(this.safeString2(settlement, 'salt', 'nonce'));
|
|
3389
|
+
const starkKey = this.convertToBigInt(this.safeString(settlement, 'starkKey'));
|
|
3390
|
+
// Order struct hash
|
|
3391
|
+
const orderHash = this.convertToBigInt(this.extendedStarknetComputePoseidonHashOnElements([
|
|
3392
|
+
orderTypeHash,
|
|
3393
|
+
positionId,
|
|
3394
|
+
this.convertToBigInt(baseAssetId),
|
|
3395
|
+
this.getExtendedEncodeI64(baseAmount),
|
|
3396
|
+
this.convertToBigInt(quoteAssetId),
|
|
3397
|
+
this.getExtendedEncodeI64(quoteAmount),
|
|
3398
|
+
this.convertToBigInt(feeAssetId),
|
|
3399
|
+
feeAmount,
|
|
3400
|
+
expiration,
|
|
3401
|
+
salt,
|
|
3402
|
+
]));
|
|
3403
|
+
// SNIP-12 final message hash: poseidon('StarkNet Message', domainHash, starkKey, orderHash)
|
|
3404
|
+
return this.extendedStarknetComputePoseidonHashOnElements([
|
|
3405
|
+
this.getExtendedStringToFelt('StarkNet Message'),
|
|
3406
|
+
domainHash,
|
|
3407
|
+
starkKey,
|
|
3408
|
+
orderHash,
|
|
3409
|
+
]);
|
|
3410
|
+
}
|
|
3411
|
+
getExtendedWithdrawalMsgHash(settlement, starkKey) {
|
|
3412
|
+
const withdrawalTypeHash = this.convertToBigInt(this.extendedStarknetGetSelectorFromName('"Withdrawal"("recipient":"felt","position_id":"PositionId","collateral_id":"AssetId","amount":"u64","expiration":"Timestamp","salt":"felt")"PositionId"("value":"u32")"AssetId"("value":"felt")"Timestamp"("seconds":"u64")'));
|
|
3413
|
+
const domainHash = this.getExtendedDomainHash();
|
|
3414
|
+
const expiration = this.safeDict(settlement, 'expiration', {});
|
|
3415
|
+
const withdrawalHash = this.convertToBigInt(this.extendedStarknetComputePoseidonHashOnElements([
|
|
3416
|
+
withdrawalTypeHash,
|
|
3417
|
+
this.convertToBigInt(this.safeString(settlement, 'recipient')),
|
|
3418
|
+
this.convertToBigInt(this.safeString(settlement, 'positionId')),
|
|
3419
|
+
this.convertToBigInt(this.safeString(settlement, 'collateralId')),
|
|
3420
|
+
this.convertToBigInt(this.safeString(settlement, 'amount')),
|
|
3421
|
+
this.convertToBigInt(this.safeString(expiration, 'seconds')),
|
|
3422
|
+
this.convertToBigInt(this.safeString(settlement, 'salt')),
|
|
3423
|
+
]));
|
|
3424
|
+
return this.extendedStarknetComputePoseidonHashOnElements([
|
|
3425
|
+
this.getExtendedStringToFelt('StarkNet Message'),
|
|
3426
|
+
domainHash,
|
|
3427
|
+
this.convertToBigInt(starkKey),
|
|
3428
|
+
withdrawalHash,
|
|
3429
|
+
]);
|
|
3430
|
+
}
|
|
3431
|
+
getExtendedTransferMsgHash(settlement) {
|
|
3432
|
+
const transferTypeHash = this.convertToBigInt(this.extendedStarknetGetSelectorFromName('"Transfer"("sender_position_id":"PositionId","receiver_position_id":"PositionId","asset_id":"AssetId","amount":"u64","expiration":"Timestamp","salt":"felt")"PositionId"("value":"u32")"AssetId"("value":"felt")"Timestamp"("seconds":"u64")'));
|
|
3433
|
+
const domainHash = this.getExtendedDomainHash();
|
|
3434
|
+
const senderPublicKey = this.convertToBigInt(this.safeString(settlement, 'senderPublicKey'));
|
|
3435
|
+
const transferHash = this.convertToBigInt(this.extendedStarknetComputePoseidonHashOnElements([
|
|
3436
|
+
transferTypeHash,
|
|
3437
|
+
this.convertToBigInt(this.safeString(settlement, 'senderPositionId')),
|
|
3438
|
+
this.convertToBigInt(this.safeString(settlement, 'receiverPositionId')),
|
|
3439
|
+
this.convertToBigInt(this.safeString(settlement, 'assetId')),
|
|
3440
|
+
this.convertToBigInt(this.safeString(settlement, 'amount')),
|
|
3441
|
+
this.convertToBigInt(this.safeString(settlement, 'expirationTimestamp')),
|
|
3442
|
+
this.convertToBigInt(this.safeString(settlement, 'nonce')),
|
|
3443
|
+
]));
|
|
3444
|
+
return this.extendedStarknetComputePoseidonHashOnElements([
|
|
3445
|
+
this.getExtendedStringToFelt('StarkNet Message'),
|
|
3446
|
+
domainHash,
|
|
3447
|
+
senderPublicKey,
|
|
3448
|
+
transferHash,
|
|
3449
|
+
]);
|
|
3450
|
+
}
|
|
3451
|
+
handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
|
3452
|
+
if (!response) {
|
|
3453
|
+
return undefined; // fallback to default error handler
|
|
3454
|
+
}
|
|
3455
|
+
//
|
|
3456
|
+
// {"status":"ERROR","error":{"code":1140,"message":"New order cost exceeds available balance","debugInfo":"Order cost 2.000000 exceeds available for trade 0\nOrder price = 200, mark price = 95.2147597125 estimated market price = 94.81"}}
|
|
3457
|
+
//
|
|
3458
|
+
const status = this.safeStringLower(response, 'status');
|
|
3459
|
+
if (status === 'error') {
|
|
3460
|
+
const error = this.safeDict(response, 'error');
|
|
3461
|
+
const errorCode = this.safeString(error, 'code');
|
|
3462
|
+
const feedback = this.id + ' ' + this.json(response);
|
|
3463
|
+
this.throwBroadlyMatchedException(this.exceptions['broad'], body, feedback);
|
|
3464
|
+
this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
|
|
3465
|
+
throw new errors.ExchangeError(feedback);
|
|
3466
|
+
}
|
|
3467
|
+
return undefined;
|
|
3468
|
+
}
|
|
3469
|
+
sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
|
3470
|
+
const version = this.safeString(api, 0);
|
|
3471
|
+
const accessibility = this.safeString(api, 1);
|
|
3472
|
+
const endpoint = '/' + this.implodeParams(path, params);
|
|
3473
|
+
const query = this.omit(params, this.extractParams(path));
|
|
3474
|
+
const queryPost = (path === 'user/deadmanswitch');
|
|
3475
|
+
let url = this.implodeHostname(this.urls['api']['rest']);
|
|
3476
|
+
if (accessibility === 'private') {
|
|
3477
|
+
// this.checkRequiredCredentials ();
|
|
3478
|
+
if (this.apiKey === undefined) {
|
|
3479
|
+
throw new errors.AuthenticationError(this.id + ' sign() requires an apiKey for private endpoints');
|
|
3480
|
+
}
|
|
3481
|
+
headers = {
|
|
3482
|
+
'X-Api-Key': this.apiKey,
|
|
3483
|
+
};
|
|
3484
|
+
if (((method === 'POST') || (method === 'PATCH')) && !queryPost) {
|
|
3485
|
+
body = this.json(query);
|
|
3486
|
+
headers['Content-Type'] = 'application/json';
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
url = url + '/api/' + version + endpoint;
|
|
3490
|
+
if ((method === 'GET' || method === 'DELETE' || queryPost) && Object.keys(query).length) {
|
|
3491
|
+
url += '?' + this.urlencodeWithArrayRepeat(query);
|
|
3492
|
+
}
|
|
3493
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
exports["default"] = extended;
|