ccxt 4.5.18 → 4.5.20

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.
Files changed (152) hide show
  1. package/README.md +7 -6
  2. package/dist/ccxt.browser.min.js +40 -16
  3. package/dist/cjs/_virtual/index.cjs.js +1459 -9
  4. package/dist/cjs/ccxt.js +8 -2
  5. package/dist/cjs/src/abstract/dydx.js +11 -0
  6. package/dist/cjs/src/base/Exchange.js +164 -10
  7. package/dist/cjs/src/base/ws/Client.js +3 -1
  8. package/dist/cjs/src/binance.js +8 -1
  9. package/dist/cjs/src/bingx.js +20 -0
  10. package/dist/cjs/src/bitget.js +43 -41
  11. package/dist/cjs/src/bybit.js +21 -23
  12. package/dist/cjs/src/deribit.js +6 -0
  13. package/dist/cjs/src/dydx.js +2454 -0
  14. package/dist/cjs/src/gate.js +4 -4
  15. package/dist/cjs/src/hibachi.js +1 -1
  16. package/dist/cjs/src/hyperliquid.js +207 -9
  17. package/dist/cjs/src/kucoin.js +711 -109
  18. package/dist/cjs/src/mexc.js +2 -3
  19. package/dist/cjs/src/pro/binance.js +59 -144
  20. package/dist/cjs/src/pro/dydx.js +418 -0
  21. package/dist/cjs/src/pro/kraken.js +4 -3
  22. package/dist/cjs/src/pro/xt.js +218 -4
  23. package/dist/cjs/src/protobuf/mexc/compiled.cjs.js +1 -0
  24. package/dist/cjs/src/static_dependencies/dydx-v4-client/cosmos/base/v1beta1/coin.js +56 -0
  25. package/dist/cjs/src/static_dependencies/dydx-v4-client/cosmos/crypto/multisig/v1beta1/multisig.js +56 -0
  26. package/dist/cjs/src/static_dependencies/dydx-v4-client/cosmos/crypto/secp256k1/keys.js +48 -0
  27. package/dist/cjs/src/static_dependencies/dydx-v4-client/cosmos/tx/signing/v1beta1/signing.js +343 -0
  28. package/dist/cjs/src/static_dependencies/dydx-v4-client/cosmos/tx/v1beta1/tx.js +717 -0
  29. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/accountplus/tx.js +60 -0
  30. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/clob_pair.js +45 -0
  31. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/order.js +380 -0
  32. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/order_removals.js +72 -0
  33. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/tx.js +211 -0
  34. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/sending/transfer.js +195 -0
  35. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/sending/tx.js +49 -0
  36. package/dist/cjs/src/static_dependencies/dydx-v4-client/dydxprotocol/subaccounts/subaccount.js +57 -0
  37. package/dist/cjs/src/static_dependencies/dydx-v4-client/google/protobuf/any.js +56 -0
  38. package/dist/cjs/src/static_dependencies/dydx-v4-client/helpers.js +79 -0
  39. package/dist/cjs/src/static_dependencies/dydx-v4-client/long/index.cjs.js +9 -0
  40. package/dist/cjs/src/static_dependencies/dydx-v4-client/onboarding.js +59 -0
  41. package/dist/cjs/src/static_dependencies/dydx-v4-client/registry.js +39 -0
  42. package/dist/cjs/src/static_dependencies/noble-hashes/pbkdf2.js +69 -0
  43. package/dist/cjs/src/static_dependencies/noble-hashes/ripemd160.js +108 -0
  44. package/dist/cjs/src/static_dependencies/noble-hashes/utils.js +50 -1
  45. package/dist/cjs/src/static_dependencies/scure-base/index.js +29 -0
  46. package/dist/cjs/src/static_dependencies/scure-bip32/index.js +278 -0
  47. package/dist/cjs/src/static_dependencies/scure-bip39/index.js +97 -0
  48. package/dist/cjs/src/static_dependencies/scure-bip39/wordlists/english.js +2060 -0
  49. package/dist/cjs/src/static_dependencies/zklink/zklink-sdk-web.js +2 -0
  50. package/dist/cjs/src/toobit.js +2 -1
  51. package/js/ccxt.d.ts +8 -2
  52. package/js/ccxt.js +6 -2
  53. package/js/src/abstract/binance.d.ts +7 -0
  54. package/js/src/abstract/binancecoinm.d.ts +7 -0
  55. package/js/src/abstract/binanceus.d.ts +7 -0
  56. package/js/src/abstract/binanceusdm.d.ts +7 -0
  57. package/js/src/abstract/bitget.d.ts +1 -0
  58. package/js/src/abstract/dydx.d.ts +61 -0
  59. package/js/src/abstract/dydx.js +11 -0
  60. package/js/src/abstract/kucoin.d.ts +1 -1
  61. package/js/src/abstract/kucoinfutures.d.ts +1 -1
  62. package/js/src/base/Exchange.d.ts +7 -0
  63. package/js/src/base/Exchange.js +163 -10
  64. package/js/src/base/ws/Client.js +3 -1
  65. package/js/src/binance.js +8 -1
  66. package/js/src/bingx.js +20 -0
  67. package/js/src/bitget.d.ts +3 -3
  68. package/js/src/bitget.js +43 -41
  69. package/js/src/bybit.d.ts +3 -3
  70. package/js/src/bybit.js +21 -23
  71. package/js/src/deribit.js +6 -0
  72. package/js/src/dydx.d.ts +364 -0
  73. package/js/src/dydx.js +2453 -0
  74. package/js/src/gate.d.ts +2 -2
  75. package/js/src/gate.js +4 -4
  76. package/js/src/hibachi.js +1 -1
  77. package/js/src/hyperliquid.d.ts +17 -0
  78. package/js/src/hyperliquid.js +207 -9
  79. package/js/src/kucoin.d.ts +48 -1
  80. package/js/src/kucoin.js +711 -109
  81. package/js/src/mexc.js +2 -3
  82. package/js/src/pro/binance.d.ts +2 -2
  83. package/js/src/pro/binance.js +59 -144
  84. package/js/src/pro/dydx.d.ts +81 -0
  85. package/js/src/pro/dydx.js +417 -0
  86. package/js/src/pro/kraken.js +4 -3
  87. package/js/src/pro/xt.d.ts +85 -2
  88. package/js/src/pro/xt.js +218 -4
  89. package/js/src/static_dependencies/dydx-v4-client/cosmos/base/v1beta1/coin.d.ts +90 -0
  90. package/js/src/static_dependencies/dydx-v4-client/cosmos/base/v1beta1/coin.js +163 -0
  91. package/js/src/static_dependencies/dydx-v4-client/cosmos/crypto/multisig/keys.d.ts +26 -0
  92. package/js/src/static_dependencies/dydx-v4-client/cosmos/crypto/multisig/keys.js +51 -0
  93. package/js/src/static_dependencies/dydx-v4-client/cosmos/crypto/multisig/v1beta1/multisig.d.ts +48 -0
  94. package/js/src/static_dependencies/dydx-v4-client/cosmos/crypto/multisig/v1beta1/multisig.js +85 -0
  95. package/js/src/static_dependencies/dydx-v4-client/cosmos/crypto/secp256k1/keys.d.ts +40 -0
  96. package/js/src/static_dependencies/dydx-v4-client/cosmos/crypto/secp256k1/keys.js +77 -0
  97. package/js/src/static_dependencies/dydx-v4-client/cosmos/tx/signing/v1beta1/signing.d.ts +162 -0
  98. package/js/src/static_dependencies/dydx-v4-client/cosmos/tx/signing/v1beta1/signing.js +329 -0
  99. package/js/src/static_dependencies/dydx-v4-client/cosmos/tx/v1beta1/tx.d.ts +460 -0
  100. package/js/src/static_dependencies/dydx-v4-client/cosmos/tx/v1beta1/tx.js +698 -0
  101. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/accountplus/tx.d.ts +127 -0
  102. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/accountplus/tx.js +286 -0
  103. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/block_rate_limit_config.d.ts +66 -0
  104. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/block_rate_limit_config.js +109 -0
  105. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/clob_pair.d.ts +127 -0
  106. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/clob_pair.js +257 -0
  107. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/equity_tier_limit_config.d.ts +48 -0
  108. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/equity_tier_limit_config.js +93 -0
  109. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/finalize_block.d.ts +23 -0
  110. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/finalize_block.js +43 -0
  111. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/liquidations.d.ts +92 -0
  112. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/liquidations.js +164 -0
  113. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/liquidations_config.d.ts +124 -0
  114. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/liquidations_config.js +196 -0
  115. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/matches.d.ts +159 -0
  116. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/matches.js +324 -0
  117. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/order.d.ts +546 -0
  118. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/order.js +872 -0
  119. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/order_removals.d.ts +84 -0
  120. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/order_removals.js +181 -0
  121. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/tx.d.ts +397 -0
  122. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/clob/tx.js +757 -0
  123. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/sending/transfer.d.ts +120 -0
  124. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/sending/transfer.js +246 -0
  125. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/sending/tx.d.ts +79 -0
  126. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/sending/tx.js +147 -0
  127. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/subaccounts/asset_position.d.ts +32 -0
  128. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/subaccounts/asset_position.js +59 -0
  129. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/subaccounts/perpetual_position.d.ts +34 -0
  130. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/subaccounts/perpetual_position.js +66 -0
  131. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/subaccounts/subaccount.d.ts +62 -0
  132. package/js/src/static_dependencies/dydx-v4-client/dydxprotocol/subaccounts/subaccount.js +111 -0
  133. package/js/src/static_dependencies/dydx-v4-client/google/protobuf/any.d.ts +207 -0
  134. package/js/src/static_dependencies/dydx-v4-client/google/protobuf/any.js +50 -0
  135. package/js/src/static_dependencies/dydx-v4-client/helpers.d.ts +82 -0
  136. package/js/src/static_dependencies/dydx-v4-client/helpers.js +172 -0
  137. package/js/src/static_dependencies/dydx-v4-client/long/index.cjs +1473 -0
  138. package/js/src/static_dependencies/dydx-v4-client/long/index.d.cts +2 -0
  139. package/js/src/static_dependencies/dydx-v4-client/onboarding.d.ts +35 -0
  140. package/js/src/static_dependencies/dydx-v4-client/onboarding.js +56 -0
  141. package/js/src/static_dependencies/dydx-v4-client/registry.d.ts +7 -0
  142. package/js/src/static_dependencies/dydx-v4-client/registry.js +36 -0
  143. package/js/src/static_dependencies/noble-hashes/utils.d.ts +1 -0
  144. package/js/src/static_dependencies/noble-hashes/utils.js +4 -0
  145. package/js/src/static_dependencies/scure-bip32/index.d.ts +49 -0
  146. package/js/src/static_dependencies/scure-bip32/index.js +295 -0
  147. package/js/src/static_dependencies/scure-bip39/index.d.ts +54 -0
  148. package/js/src/static_dependencies/scure-bip39/index.js +140 -0
  149. package/js/src/static_dependencies/scure-bip39/wordlists/english.d.ts +1 -0
  150. package/js/src/static_dependencies/scure-bip39/wordlists/english.js +2054 -0
  151. package/js/src/toobit.js +2 -1
  152. package/package.json +9 -3
@@ -0,0 +1,2454 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var dydx$1 = require('./abstract/dydx.js');
6
+ var errors = require('./base/errors.js');
7
+ var number = require('./base/functions/number.js');
8
+ var Precise = require('./base/Precise.js');
9
+ var sha3 = require('./static_dependencies/noble-hashes/sha3.js');
10
+ var secp256k1 = require('./static_dependencies/noble-curves/secp256k1.js');
11
+ var crypto = require('./base/functions/crypto.js');
12
+
13
+ // ----------------------------------------------------------------------------
14
+ // ---------------------------------------------------------------------------
15
+ /**
16
+ * @class dydx
17
+ * @augments Exchange
18
+ */
19
+ class dydx extends dydx$1["default"] {
20
+ describe() {
21
+ return this.deepExtend(super.describe(), {
22
+ 'id': 'dydx',
23
+ 'name': 'dYdX',
24
+ 'countries': ['US'],
25
+ 'rateLimit': 100,
26
+ 'version': 'v4',
27
+ 'certified': false,
28
+ 'dex': true,
29
+ 'pro': true,
30
+ 'has': {
31
+ 'CORS': undefined,
32
+ 'spot': false,
33
+ 'margin': false,
34
+ 'swap': true,
35
+ 'future': false,
36
+ 'option': false,
37
+ 'addMargin': false,
38
+ 'cancelAllOrders': false,
39
+ 'cancelAllOrdersAfter': false,
40
+ 'cancelOrder': true,
41
+ 'cancelOrders': true,
42
+ 'cancelWithdraw': false,
43
+ 'closeAllPositions': false,
44
+ 'closePosition': false,
45
+ 'createConvertTrade': false,
46
+ 'createDepositAddress': false,
47
+ 'createMarketBuyOrderWithCost': false,
48
+ 'createMarketOrder': false,
49
+ 'createMarketOrderWithCost': false,
50
+ 'createMarketSellOrderWithCost': false,
51
+ 'createOrder': true,
52
+ 'createOrderWithTakeProfitAndStopLoss': 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
+ 'fetchAccounts': true,
63
+ 'fetchBalance': true,
64
+ 'fetchCanceledOrders': false,
65
+ 'fetchClosedOrder': false,
66
+ 'fetchClosedOrders': true,
67
+ 'fetchConvertCurrencies': false,
68
+ 'fetchConvertQuote': false,
69
+ 'fetchConvertTrade': false,
70
+ 'fetchConvertTradeHistory': false,
71
+ 'fetchCurrencies': false,
72
+ 'fetchDepositAddress': false,
73
+ 'fetchDepositAddresses': false,
74
+ 'fetchDepositAddressesByNetwork': false,
75
+ 'fetchDeposits': true,
76
+ 'fetchDepositsWithdrawals': true,
77
+ 'fetchFundingHistory': false,
78
+ 'fetchFundingInterval': false,
79
+ 'fetchFundingIntervals': false,
80
+ 'fetchFundingRate': false,
81
+ 'fetchFundingRateHistory': true,
82
+ 'fetchFundingRates': false,
83
+ 'fetchIndexOHLCV': false,
84
+ 'fetchLedger': true,
85
+ 'fetchLeverage': false,
86
+ 'fetchMarginAdjustmentHistory': false,
87
+ 'fetchMarginMode': false,
88
+ 'fetchMarkets': true,
89
+ 'fetchMarkOHLCV': false,
90
+ 'fetchMyTrades': false,
91
+ 'fetchOHLCV': true,
92
+ 'fetchOpenInterestHistory': false,
93
+ 'fetchOpenOrder': false,
94
+ 'fetchOpenOrders': true,
95
+ 'fetchOrder': true,
96
+ 'fetchOrderBook': true,
97
+ 'fetchOrders': true,
98
+ 'fetchOrderTrades': false,
99
+ 'fetchPosition': true,
100
+ 'fetchPositionHistory': false,
101
+ 'fetchPositionMode': false,
102
+ 'fetchPositions': true,
103
+ 'fetchPositionsHistory': false,
104
+ 'fetchPremiumIndexOHLCV': false,
105
+ 'fetchStatus': false,
106
+ 'fetchTicker': false,
107
+ 'fetchTickers': false,
108
+ 'fetchTime': true,
109
+ 'fetchTrades': true,
110
+ 'fetchTradingFee': false,
111
+ 'fetchTradingFees': false,
112
+ 'fetchTransactions': false,
113
+ 'fetchTransfers': true,
114
+ 'fetchWithdrawals': true,
115
+ 'reduceMargin': false,
116
+ 'sandbox': false,
117
+ 'setLeverage': false,
118
+ 'setMargin': false,
119
+ 'setPositionMode': false,
120
+ 'transfer': true,
121
+ 'withdraw': true,
122
+ },
123
+ 'timeframes': {
124
+ '1m': '1MIN',
125
+ '5m': '5MINS',
126
+ '15m': '15MINS',
127
+ '30m': '30MINS',
128
+ '1h': '1HOUR',
129
+ '4h': '4HOURS',
130
+ '1d': '1DAY',
131
+ },
132
+ 'urls': {
133
+ 'logo': 'https://github.com/user-attachments/assets/617ea0c1-f05a-4d26-9fcb-a0d1d4091ae1',
134
+ 'api': {
135
+ 'indexer': 'https://indexer.dydx.trade/v4',
136
+ 'nodeRpc': 'https://dydx-ops-rpc.kingnodes.com',
137
+ 'nodeRest': 'https://dydx-rest.publicnode.com',
138
+ },
139
+ 'test': {
140
+ 'indexer': 'https://indexer.v4testnet.dydx.exchange/v4',
141
+ 'nodeRpc': 'https://test-dydx-rpc.kingnodes.com',
142
+ 'nodeRest': 'https://test-dydx-rest.kingnodes.com',
143
+ },
144
+ 'www': 'https://www.dydx.xyz',
145
+ 'doc': [
146
+ 'https://docs.dydx.xyz',
147
+ ],
148
+ 'fees': [
149
+ 'https://docs.dydx.exchange/introduction-trading_fees',
150
+ ],
151
+ 'referral': 'dydx.trade?ref=ccxt',
152
+ },
153
+ 'api': {
154
+ 'indexer': {
155
+ 'get': {
156
+ 'addresses/{address}': 1,
157
+ 'addresses/{address}/parentSubaccountNumber/{number}': 1,
158
+ 'addresses/{address}/subaccountNumber/{subaccountNumber}': 1,
159
+ 'assetPositions': 1,
160
+ 'assetPositions/parentSubaccountNumber': 1,
161
+ 'candles/perpetualMarkets/{market}': 1,
162
+ 'compliance/screen/{address}': 1,
163
+ 'fills': 1,
164
+ 'fills/parentSubaccountNumber': 1,
165
+ 'fundingPayments': 1,
166
+ 'fundingPayments/parentSubaccount': 1,
167
+ 'height': 0.1,
168
+ 'historical-pnl': 1,
169
+ 'historical-pnl/parentSubaccountNumber': 1,
170
+ 'historicalBlockTradingRewards/{address}': 1,
171
+ 'historicalFunding/{market}': 1,
172
+ 'historicalTradingRewardAggregations/{address}': 1,
173
+ 'orderbooks/perpetualMarket/{market}': 1,
174
+ 'orders': 1,
175
+ 'orders/parentSubaccountNumber': 1,
176
+ 'orders/{orderId}': 1,
177
+ 'perpetualMarkets': 1,
178
+ 'perpetualPositions': 1,
179
+ 'perpetualPositions/parentSubaccountNumber': 1,
180
+ 'screen': 1,
181
+ 'sparklines': 1,
182
+ 'time': 1,
183
+ 'trades/perpetualMarket/{market}': 1,
184
+ 'transfers': 1,
185
+ 'transfers/between': 1,
186
+ 'transfers/parentSubaccountNumber': 1,
187
+ 'vault/v1/megavault/historicalPnl': 1,
188
+ 'vault/v1/megavault/positions': 1,
189
+ 'vault/v1/vaults/historicalPnl': 1,
190
+ //
191
+ 'perpetualMarketSparklines': 1,
192
+ 'perpetualMarkets/{ticker}': 1,
193
+ 'perpetualMarkets/{ticker}/orderbook': 1,
194
+ 'trades/perpetualMarket/{ticker}': 1,
195
+ 'historicalFunding/{ticker}': 1,
196
+ 'candles/{ticker}/{resolution}': 1,
197
+ 'addresses/{address}/subaccounts': 1,
198
+ 'addresses/{address}/subaccountNumber/{subaccountNumber}/assetPositions': 1,
199
+ 'addresses/{address}/subaccountNumber/{subaccountNumber}/perpetualPositions': 1,
200
+ 'addresses/{address}/subaccountNumber/{subaccountNumber}/orders': 1,
201
+ 'fills/parentSubaccount': 1,
202
+ 'historical-pnl/parentSubaccount': 1,
203
+ },
204
+ },
205
+ 'nodeRpc': {
206
+ 'get': {
207
+ 'abci_info': 1,
208
+ 'block': 1,
209
+ 'broadcast_tx_async': 1,
210
+ 'broadcast_tx_sync': 1,
211
+ 'tx': 1,
212
+ },
213
+ },
214
+ 'nodeRest': {
215
+ 'get': {
216
+ 'cosmos/auth/v1beta1/account_info/{dydxAddress}': 1,
217
+ },
218
+ 'post': {
219
+ 'cosmos/tx/v1beta1/encode': 1,
220
+ 'cosmos/tx/v1beta1/simulate': 1,
221
+ },
222
+ },
223
+ },
224
+ 'fees': {
225
+ 'trading': {
226
+ 'tierBased': true,
227
+ 'percentage': true,
228
+ 'maker': this.parseNumber('0.0001'),
229
+ 'taker': this.parseNumber('0.0005'),
230
+ },
231
+ },
232
+ 'requiredCredentials': {
233
+ 'apiKey': false,
234
+ 'secret': false,
235
+ 'privateKey': false,
236
+ },
237
+ 'options': {
238
+ 'mnemonic': undefined,
239
+ 'chainName': 'dydx-mainnet-1',
240
+ 'chainId': 1,
241
+ 'sandboxMode': false,
242
+ 'defaultFeeDenom': 'uusdc',
243
+ 'defaultFeeMultiplier': '1.6',
244
+ 'feeDenom': {
245
+ 'USDC_DENOM': 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
246
+ 'USDC_GAS_DENOM': 'uusdc',
247
+ 'USDC_DECIMALS': 6,
248
+ 'USDC_GAS_PRICE': '0.025',
249
+ 'CHAINTOKEN_DENOM': 'adydx',
250
+ 'CHAINTOKEN_DECIMALS': 18,
251
+ 'CHAINTOKEN_GAS_PRICE': '25000000000',
252
+ },
253
+ },
254
+ 'features': {
255
+ 'default': {
256
+ 'sandbox': true,
257
+ 'createOrder': {
258
+ 'marginMode': false,
259
+ 'triggerPrice': true,
260
+ 'triggerPriceType': {
261
+ 'last': true,
262
+ 'mark': true,
263
+ 'index': false,
264
+ },
265
+ 'triggerDirection': false,
266
+ 'stopLossPrice': false,
267
+ 'takeProfitPrice': false,
268
+ 'attachedStopLossTakeProfit': undefined,
269
+ 'timeInForce': {
270
+ 'IOC': true,
271
+ 'FOK': true,
272
+ 'PO': true,
273
+ 'GTD': true,
274
+ },
275
+ 'hedged': false,
276
+ 'trailing': false,
277
+ 'leverage': false,
278
+ 'marketBuyByCost': false,
279
+ 'marketBuyRequiresPrice': false,
280
+ 'selfTradePrevention': false,
281
+ 'iceberg': false,
282
+ },
283
+ 'createOrders': undefined,
284
+ 'fetchMyTrades': {
285
+ 'marginMode': false,
286
+ 'limit': 500,
287
+ 'daysBack': 90,
288
+ 'untilDays': 10000,
289
+ 'symbolRequired': false,
290
+ },
291
+ 'fetchOrder': {
292
+ 'marginMode': false,
293
+ 'trigger': true,
294
+ 'trailing': false,
295
+ 'symbolRequired': false,
296
+ },
297
+ 'fetchOpenOrders': {
298
+ 'marginMode': false,
299
+ 'limit': 500,
300
+ 'trigger': true,
301
+ 'trailing': true,
302
+ 'symbolRequired': false,
303
+ },
304
+ 'fetchOrders': {
305
+ 'marginMode': false,
306
+ 'limit': 500,
307
+ 'daysBack': undefined,
308
+ 'untilDays': 100000,
309
+ 'trigger': true,
310
+ 'trailing': true,
311
+ 'symbolRequired': false,
312
+ },
313
+ 'fetchClosedOrders': {
314
+ 'marginMode': false,
315
+ 'limit': 500,
316
+ 'daysBack': undefined,
317
+ 'daysBackCanceled': undefined,
318
+ 'untilDays': 100000,
319
+ 'trigger': true,
320
+ 'trailing': true,
321
+ 'symbolRequired': false,
322
+ },
323
+ 'fetchOHLCV': {
324
+ 'limit': 1000,
325
+ },
326
+ },
327
+ 'forSwap': {
328
+ 'extends': 'default',
329
+ 'createOrder': {
330
+ 'hedged': true,
331
+ },
332
+ },
333
+ 'swap': {
334
+ 'linear': {
335
+ 'extends': 'forSwap',
336
+ },
337
+ 'inverse': undefined,
338
+ },
339
+ 'future': {
340
+ 'linear': undefined,
341
+ 'inverse': undefined,
342
+ },
343
+ },
344
+ 'commonCurrencies': {},
345
+ 'exceptions': {
346
+ 'exact': {
347
+ // error collision for clob and sending modules from 2 - 8
348
+ // https://github.com/dydxprotocol/v4-chain/blob/5f9f6c9b95cc87d732e23de764909703b81a6e8b/protocol/x/clob/types/errors.go#L320
349
+ // https://github.com/dydxprotocol/v4-chain/blob/5f9f6c9b95cc87d732e23de764909703b81a6e8b/protocol/x/sending/types/errors.go
350
+ '9': errors.InvalidOrder,
351
+ '10': errors.InvalidOrder,
352
+ '11': errors.InvalidOrder,
353
+ '12': errors.InvalidOrder,
354
+ '13': errors.InvalidOrder,
355
+ '14': errors.InvalidOrder,
356
+ '15': errors.InvalidOrder,
357
+ '16': errors.InvalidOrder,
358
+ '17': errors.InvalidOrder,
359
+ '18': errors.InvalidOrder,
360
+ '19': errors.InvalidOrder,
361
+ '20': errors.InvalidOrder,
362
+ '21': errors.InvalidOrder,
363
+ '22': errors.InvalidOrder,
364
+ '23': errors.InvalidOrder,
365
+ '24': errors.InvalidOrder,
366
+ '25': errors.InvalidOrder,
367
+ '26': errors.InvalidOrder,
368
+ '27': errors.InvalidOrder,
369
+ '28': errors.InvalidOrder,
370
+ '29': errors.InvalidOrder,
371
+ '30': errors.InvalidOrder,
372
+ '31': errors.InvalidOrder,
373
+ '32': errors.InvalidOrder,
374
+ '33': errors.InvalidOrder,
375
+ '34': errors.InvalidOrder,
376
+ '35': errors.InvalidOrder,
377
+ '36': errors.InvalidOrder,
378
+ '37': errors.InvalidOrder,
379
+ '39': errors.InvalidOrder,
380
+ '40': errors.InvalidOrder,
381
+ '41': errors.InvalidOrder,
382
+ '42': errors.InvalidOrder,
383
+ '43': errors.InvalidOrder,
384
+ '44': errors.InvalidOrder,
385
+ '45': errors.InvalidOrder,
386
+ '46': errors.InvalidOrder,
387
+ '47': errors.InvalidOrder,
388
+ '48': errors.InvalidOrder,
389
+ '49': errors.InvalidOrder,
390
+ '50': errors.InvalidOrder,
391
+ '1000': errors.BadRequest,
392
+ '1001': errors.BadRequest,
393
+ '1002': errors.BadRequest,
394
+ '1003': errors.InvalidOrder,
395
+ '1004': errors.InvalidOrder,
396
+ '1005': errors.InvalidOrder,
397
+ '1006': errors.InvalidOrder,
398
+ '1007': errors.InvalidOrder,
399
+ '1008': errors.InvalidOrder,
400
+ '1009': errors.InvalidOrder,
401
+ '1010': errors.InvalidOrder,
402
+ '1011': errors.InvalidOrder,
403
+ '1012': errors.InvalidOrder,
404
+ '1013': errors.InvalidOrder,
405
+ '1014': errors.InvalidOrder,
406
+ '1015': errors.InvalidOrder,
407
+ '1017': errors.InvalidOrder,
408
+ '1018': errors.InvalidOrder,
409
+ '1019': errors.InvalidOrder,
410
+ '1020': errors.InvalidOrder,
411
+ '1021': errors.InvalidOrder,
412
+ '1022': errors.InvalidOrder,
413
+ '2000': errors.InvalidOrder,
414
+ '2001': errors.InvalidOrder,
415
+ '2002': errors.InvalidOrder,
416
+ '2003': errors.InvalidOrder,
417
+ '2004': errors.InvalidOrder,
418
+ '2005': errors.InvalidOrder,
419
+ '3000': errors.InvalidOrder,
420
+ '3001': errors.InvalidOrder,
421
+ '3002': errors.InvalidOrder,
422
+ '3003': errors.InvalidOrder,
423
+ '3004': errors.InvalidOrder,
424
+ '3005': errors.InvalidOrder,
425
+ '3006': errors.InvalidOrder,
426
+ '3007': errors.InvalidOrder,
427
+ '3008': errors.InvalidOrder,
428
+ '3009': errors.InvalidOrder,
429
+ '3010': errors.InvalidOrder,
430
+ '4000': errors.InvalidOrder,
431
+ '4001': errors.InvalidOrder,
432
+ '4002': errors.InvalidOrder,
433
+ '4003': errors.InvalidOrder,
434
+ '4004': errors.InvalidOrder,
435
+ '4005': errors.InvalidOrder,
436
+ '4006': errors.InvalidOrder,
437
+ '4007': errors.InvalidOrder,
438
+ '4008': errors.InvalidOrder,
439
+ '5000': errors.InvalidOrder,
440
+ '5001': errors.InvalidOrder,
441
+ '6000': errors.InvalidOrder,
442
+ '6001': errors.InvalidOrder,
443
+ '6002': errors.InvalidOrder,
444
+ '9000': errors.InvalidOrder,
445
+ '9001': errors.InvalidOrder,
446
+ '9002': errors.InvalidOrder,
447
+ '9003': errors.InvalidOrder,
448
+ '10000': errors.InvalidOrder,
449
+ '10001': errors.InvalidOrder,
450
+ '11000': errors.InvalidOrder, // Invalid order router address
451
+ },
452
+ 'broad': {
453
+ 'insufficient funds': errors.InsufficientFunds,
454
+ },
455
+ },
456
+ 'precisionMode': number.TICK_SIZE,
457
+ });
458
+ }
459
+ /**
460
+ * @method
461
+ * @name dydx#fetchTime
462
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
463
+ * @see https://docs.dydx.xyz/indexer-client/http#get-time
464
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
465
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
466
+ */
467
+ async fetchTime(params = {}) {
468
+ const response = await this.indexerGetTime(params);
469
+ //
470
+ // {
471
+ // "iso": "2025-07-20T15:12:13.466Z",
472
+ // "epoch": 1753024333.466
473
+ // }
474
+ //
475
+ return this.safeInteger(response, 'epoch');
476
+ }
477
+ parseMarket(market) {
478
+ //
479
+ // {
480
+ // "clobPairId": "0",
481
+ // "ticker": "BTC-USD",
482
+ // "status": "ACTIVE",
483
+ // "oraclePrice": "118976.5376",
484
+ // "priceChange24H": "659.9736",
485
+ // "volume24H": "1292729.3605",
486
+ // "trades24H": 9387,
487
+ // "nextFundingRate": "0",
488
+ // "initialMarginFraction": "0.02",
489
+ // "maintenanceMarginFraction": "0.012",
490
+ // "openInterest": "52.0691",
491
+ // "atomicResolution": -10,
492
+ // "quantumConversionExponent": -9,
493
+ // "tickSize": "1",
494
+ // "stepSize": "0.0001",
495
+ // "stepBaseQuantums": 1000000,
496
+ // "subticksPerTick": 100000,
497
+ // "marketType": "CROSS",
498
+ // "openInterestLowerCap": "0",
499
+ // "openInterestUpperCap": "0",
500
+ // "baseOpenInterest": "50.3776",
501
+ // "defaultFundingRate1H": "0"
502
+ // }
503
+ //
504
+ const quoteId = 'USDC';
505
+ const marketId = this.safeString(market, 'ticker');
506
+ const parts = marketId.split('-');
507
+ const baseName = this.safeString(parts, 0);
508
+ const base = this.safeCurrencyCode(baseName);
509
+ const quote = this.safeCurrencyCode(quoteId);
510
+ const baseId = this.safeString(market, 'baseId');
511
+ const settleId = 'USDC';
512
+ const settle = this.safeCurrencyCode(settleId);
513
+ const symbol = base + '/' + quote + ':' + settle;
514
+ const contract = true;
515
+ const swap = true;
516
+ const amountPrecisionStr = this.safeString(market, 'stepSize');
517
+ const pricePrecisionStr = this.safeString(market, 'tickSize');
518
+ const status = this.safeString(market, 'status');
519
+ let active = true;
520
+ if (status !== 'ACTIVE') {
521
+ active = false;
522
+ }
523
+ return this.safeMarketStructure({
524
+ 'id': this.safeString(market, 'ticker'),
525
+ 'symbol': symbol,
526
+ 'base': base,
527
+ 'quote': quote,
528
+ 'settle': settle,
529
+ 'baseId': baseId,
530
+ 'baseName': baseName,
531
+ 'quoteId': quoteId,
532
+ 'settleId': settleId,
533
+ 'type': 'swap',
534
+ 'spot': false,
535
+ 'margin': undefined,
536
+ 'swap': swap,
537
+ 'future': false,
538
+ 'option': false,
539
+ 'active': active,
540
+ 'contract': contract,
541
+ 'linear': true,
542
+ 'inverse': false,
543
+ 'taker': undefined,
544
+ 'maker': undefined,
545
+ 'contractSize': undefined,
546
+ 'expiry': undefined,
547
+ 'expiryDatetime': undefined,
548
+ 'strike': undefined,
549
+ 'optionType': undefined,
550
+ 'precision': {
551
+ 'amount': this.parseNumber(amountPrecisionStr),
552
+ 'price': this.parseNumber(pricePrecisionStr),
553
+ },
554
+ 'limits': {
555
+ 'leverage': {
556
+ 'min': undefined,
557
+ 'max': undefined,
558
+ },
559
+ 'amount': {
560
+ 'min': undefined,
561
+ 'max': undefined,
562
+ },
563
+ 'price': {
564
+ 'min': undefined,
565
+ 'max': undefined,
566
+ },
567
+ 'cost': {
568
+ 'min': undefined,
569
+ 'max': undefined,
570
+ },
571
+ },
572
+ 'created': undefined,
573
+ 'info': market,
574
+ });
575
+ }
576
+ /**
577
+ * @method
578
+ * @name dydx#fetchMarkets
579
+ * @description retrieves data on all markets for hyperliquid
580
+ * @see https://docs.dydx.xyz/indexer-client/http#get-perpetual-markets
581
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
582
+ * @returns {object[]} an array of objects representing market data
583
+ */
584
+ async fetchMarkets(params = {}) {
585
+ const request = {
586
+ // 'limit': 1000,
587
+ };
588
+ const response = await this.indexerGetPerpetualMarkets(this.extend(request, params));
589
+ //
590
+ // {
591
+ // "markets": {
592
+ // "BTC-USD": {
593
+ // "clobPairId": "0",
594
+ // "ticker": "BTC-USD",
595
+ // "status": "ACTIVE",
596
+ // "oraclePrice": "118976.5376",
597
+ // "priceChange24H": "659.9736",
598
+ // "volume24H": "1292729.3605",
599
+ // "trades24H": 9387,
600
+ // "nextFundingRate": "0",
601
+ // "initialMarginFraction": "0.02",
602
+ // "maintenanceMarginFraction": "0.012",
603
+ // "openInterest": "52.0691",
604
+ // "atomicResolution": -10,
605
+ // "quantumConversionExponent": -9,
606
+ // "tickSize": "1",
607
+ // "stepSize": "0.0001",
608
+ // "stepBaseQuantums": 1000000,
609
+ // "subticksPerTick": 100000,
610
+ // "marketType": "CROSS",
611
+ // "openInterestLowerCap": "0",
612
+ // "openInterestUpperCap": "0",
613
+ // "baseOpenInterest": "50.3776",
614
+ // "defaultFundingRate1H": "0"
615
+ // }
616
+ // }
617
+ // }
618
+ //
619
+ const data = this.safeDict(response, 'markets', {});
620
+ const markets = Object.values(data);
621
+ return this.parseMarkets(markets);
622
+ }
623
+ parseTrade(trade, market = undefined) {
624
+ //
625
+ // {
626
+ // "id": "02ac5b1f0000000200000002",
627
+ // "side": "BUY",
628
+ // "size": "0.0501",
629
+ // "price": "115732",
630
+ // "type": "LIMIT",
631
+ // "createdAt": "2025-07-25T05:11:09.800Z",
632
+ // "createdAtHeight": "44849951"
633
+ // }
634
+ //
635
+ const timestamp = this.parse8601(this.safeString(trade, 'createdAt'));
636
+ const symbol = market['symbol'];
637
+ const price = this.safeString(trade, 'price');
638
+ const amount = this.safeString(trade, 'size');
639
+ const side = this.safeStringLower(trade, 'side');
640
+ const id = this.safeString(trade, 'id');
641
+ return this.safeTrade({
642
+ 'id': id,
643
+ 'timestamp': timestamp,
644
+ 'datetime': this.iso8601(timestamp),
645
+ 'symbol': symbol,
646
+ 'side': side,
647
+ 'price': price,
648
+ 'amount': amount,
649
+ 'cost': undefined,
650
+ 'order': undefined,
651
+ 'takerOrMaker': undefined,
652
+ 'type': undefined,
653
+ 'fee': undefined,
654
+ 'info': trade,
655
+ }, market);
656
+ }
657
+ /**
658
+ * @method
659
+ * @name dydx#fetchTrades
660
+ * @description get the list of most recent trades for a particular symbol
661
+ * @see https://developer.woox.io/api-reference/endpoint/public_data/marketTrades
662
+ * @param {string} symbol unified symbol of the market to fetch trades for
663
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
664
+ * @param {int} [limit] the maximum amount of trades to fetch
665
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
666
+ * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
667
+ */
668
+ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
669
+ await this.loadMarkets();
670
+ const market = this.market(symbol);
671
+ const request = {
672
+ 'market': market['id'],
673
+ };
674
+ if (limit !== undefined) {
675
+ request['limit'] = limit;
676
+ }
677
+ const response = await this.indexerGetTradesPerpetualMarketMarket(this.extend(request, params));
678
+ //
679
+ // {
680
+ // "trades": [
681
+ // {
682
+ // "id": "02ac5b1f0000000200000002",
683
+ // "side": "BUY",
684
+ // "size": "0.0501",
685
+ // "price": "115732",
686
+ // "type": "LIMIT",
687
+ // "createdAt": "2025-07-25T05:11:09.800Z",
688
+ // "createdAtHeight": "44849951"
689
+ // }
690
+ // ]
691
+ // }
692
+ //
693
+ const rows = this.safeList(response, 'trades', []);
694
+ return this.parseTrades(rows, market, since, limit);
695
+ }
696
+ parseOHLCV(ohlcv, market = undefined) {
697
+ //
698
+ // {
699
+ // "startedAt": "2025-07-25T09:47:00.000Z",
700
+ // "ticker": "BTC-USD",
701
+ // "resolution": "1MIN",
702
+ // "low": "116099",
703
+ // "high": "116099",
704
+ // "open": "116099",
705
+ // "close": "116099",
706
+ // "baseTokenVolume": "0",
707
+ // "usdVolume": "0",
708
+ // "trades": 0,
709
+ // "startingOpenInterest": "54.0594",
710
+ // "orderbookMidPriceOpen": "115845.5",
711
+ // "orderbookMidPriceClose": "115845.5"
712
+ // }
713
+ //
714
+ return [
715
+ this.parse8601(this.safeString(ohlcv, 'startedAt')),
716
+ this.safeNumber(ohlcv, 'open'),
717
+ this.safeNumber(ohlcv, 'high'),
718
+ this.safeNumber(ohlcv, 'low'),
719
+ this.safeNumber(ohlcv, 'close'),
720
+ this.safeNumber(ohlcv, 'baseTokenVolume'),
721
+ ];
722
+ }
723
+ /**
724
+ * @method
725
+ * @name dydx#fetchOHLCV
726
+ * @see https://docs.dydx.xyz/indexer-client/http#get-candles
727
+ * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
728
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
729
+ * @param {string} timeframe the length of time each candle represents
730
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
731
+ * @param {int} [limit] the maximum amount of candles to fetch
732
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
733
+ * @param {int} [params.until] the latest time in ms to fetch entries for
734
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
735
+ */
736
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
737
+ await this.loadMarkets();
738
+ const market = this.market(symbol);
739
+ const request = {
740
+ 'market': market['id'],
741
+ 'resolution': this.safeString(this.timeframes, timeframe, timeframe),
742
+ };
743
+ if (limit !== undefined) {
744
+ request['limit'] = Math.min(limit, 1000);
745
+ }
746
+ if (since !== undefined) {
747
+ request['fromIso'] = this.iso8601(since);
748
+ }
749
+ const until = this.safeInteger(params, 'until');
750
+ params = this.omit(params, 'until');
751
+ if (until !== undefined) {
752
+ request['toIso'] = this.iso8601(until);
753
+ }
754
+ const response = await this.indexerGetCandlesPerpetualMarketsMarket(this.extend(request, params));
755
+ //
756
+ // {
757
+ // "candles": [
758
+ // {
759
+ // "startedAt": "2025-07-25T09:47:00.000Z",
760
+ // "ticker": "BTC-USD",
761
+ // "resolution": "1MIN",
762
+ // "low": "116099",
763
+ // "high": "116099",
764
+ // "open": "116099",
765
+ // "close": "116099",
766
+ // "baseTokenVolume": "0",
767
+ // "usdVolume": "0",
768
+ // "trades": 0,
769
+ // "startingOpenInterest": "54.0594",
770
+ // "orderbookMidPriceOpen": "115845.5",
771
+ // "orderbookMidPriceClose": "115845.5"
772
+ // }
773
+ // ]
774
+ // }
775
+ //
776
+ const rows = this.safeList(response, 'candles', []);
777
+ return this.parseOHLCVs(rows, market, timeframe, since, limit);
778
+ }
779
+ /**
780
+ * @method
781
+ * @name dydx#fetchFundingRateHistory
782
+ * @description fetches historical funding rate prices
783
+ * @see https://docs.dydx.xyz/indexer-client/http#get-historical-funding
784
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
785
+ * @param {int} [since] timestamp in ms of the earliest funding rate to fetch
786
+ * @param {int} [limit] the maximum amount of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure} to fetch
787
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
788
+ * @param {int} [params.until] timestamp in ms of the latest funding rate
789
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
790
+ */
791
+ async fetchFundingRateHistory(symbol = undefined, since = undefined, limit = undefined, params = {}) {
792
+ if (symbol === undefined) {
793
+ throw new errors.ArgumentsRequired(this.id + ' fetchFundingRateHistory() requires a symbol argument');
794
+ }
795
+ await this.loadMarkets();
796
+ const market = this.market(symbol);
797
+ const request = {
798
+ 'market': market['id'],
799
+ };
800
+ if (limit !== undefined) {
801
+ request['limit'] = limit;
802
+ }
803
+ const until = this.safeInteger(params, 'until');
804
+ if (until !== undefined) {
805
+ request['effectiveBeforeOrAt'] = this.iso8601(until);
806
+ }
807
+ const response = await this.indexerGetHistoricalFundingMarket(this.extend(request, params));
808
+ //
809
+ // {
810
+ // "historicalFunding": [
811
+ // {
812
+ // "ticker": "BTC-USD",
813
+ // "rate": "0",
814
+ // "price": "116302.62419",
815
+ // "effectiveAtHeight": "44865196",
816
+ // "effectiveAt": "2025-07-25T11:00:00.013Z"
817
+ // }
818
+ // ]
819
+ // }
820
+ //
821
+ const rates = [];
822
+ const rows = this.safeList(response, 'historicalFunding', []);
823
+ for (let i = 0; i < rows.length; i++) {
824
+ const entry = rows[i];
825
+ const timestamp = this.parse8601(this.safeString(entry, 'effectiveAt'));
826
+ const marketId = this.safeString(entry, 'ticker');
827
+ rates.push({
828
+ 'info': entry,
829
+ 'symbol': this.safeSymbol(marketId, market),
830
+ 'fundingRate': this.safeNumber(entry, 'rate'),
831
+ 'timestamp': timestamp,
832
+ 'datetime': this.iso8601(timestamp),
833
+ });
834
+ }
835
+ const sorted = this.sortBy(rates, 'timestamp');
836
+ return this.filterBySymbolSinceLimit(sorted, symbol, since, limit);
837
+ }
838
+ handlePublicAddress(methodName, params) {
839
+ let userAux = undefined;
840
+ [userAux, params] = this.handleOptionAndParams(params, methodName, 'user');
841
+ let user = userAux;
842
+ [user, params] = this.handleOptionAndParams(params, methodName, 'address', userAux);
843
+ if ((user !== undefined) && (user !== '')) {
844
+ return [user, params];
845
+ }
846
+ if ((this.walletAddress !== undefined) && (this.walletAddress !== '')) {
847
+ return [this.walletAddress, params];
848
+ }
849
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() requires a user parameter inside \'params\' or the walletAddress set');
850
+ }
851
+ parseOrder(order, market = undefined) {
852
+ //
853
+ // {
854
+ // "id": "dad46410-3444-5566-a129-19a619300fb7",
855
+ // "subaccountId": "8586bcf6-1f58-5ec9-a0bc-e53db273e7b0",
856
+ // "clientId": "716238006",
857
+ // "clobPairId": "0",
858
+ // "side": "BUY",
859
+ // "size": "0.001",
860
+ // "totalFilled": "0.001",
861
+ // "price": "400000",
862
+ // "type": "LIMIT",
863
+ // "status": "FILLED",
864
+ // "timeInForce": "GTT",
865
+ // "reduceOnly": false,
866
+ // "orderFlags": "64",
867
+ // "goodTilBlockTime": "2025-07-28T12:07:33.000Z",
868
+ // "createdAtHeight": "45058325",
869
+ // "clientMetadata": "2",
870
+ // "updatedAt": "2025-07-28T12:06:35.330Z",
871
+ // "updatedAtHeight": "45058326",
872
+ // "postOnly": false,
873
+ // "ticker": "BTC-USD",
874
+ // "subaccountNumber": 0
875
+ // }
876
+ //
877
+ const status = this.parseOrderStatus(this.safeStringUpper(order, 'status'));
878
+ const marketId = this.safeString(order, 'ticker');
879
+ const symbol = this.safeSymbol(marketId, market);
880
+ const filled = this.safeString(order, 'totalFilled');
881
+ const timestamp = this.parse8601(this.safeString(order, 'updatedAt'));
882
+ const price = this.safeString(order, 'price');
883
+ const amount = this.safeString(order, 'size');
884
+ const type = this.parseOrderType(this.safeStringUpper(order, 'type'));
885
+ const side = this.safeStringLower(order, 'side');
886
+ const timeInForce = this.safeStringUpper(order, 'timeInForce');
887
+ return this.safeOrder({
888
+ 'info': order,
889
+ 'id': this.safeString(order, 'id'),
890
+ 'clientOrderId': this.safeString(order, 'clientId'),
891
+ 'timestamp': timestamp,
892
+ 'datetime': this.iso8601(timestamp),
893
+ 'lastTradeTimestamp': undefined,
894
+ 'lastUpdateTimestamp': timestamp,
895
+ 'symbol': symbol,
896
+ 'type': type,
897
+ 'timeInForce': timeInForce,
898
+ 'postOnly': this.safeBool(order, 'postOnly'),
899
+ 'reduceOnly': this.safeBool(order, 'reduceOnly'),
900
+ 'side': side,
901
+ 'price': price,
902
+ 'triggerPrice': undefined,
903
+ 'amount': amount,
904
+ 'cost': undefined,
905
+ 'average': undefined,
906
+ 'filled': filled,
907
+ 'remaining': undefined,
908
+ 'status': status,
909
+ 'fee': undefined,
910
+ 'trades': undefined,
911
+ }, market);
912
+ }
913
+ parseOrderStatus(status) {
914
+ const statuses = {
915
+ 'UNTRIGGERED': 'open',
916
+ 'OPEN': 'open',
917
+ 'FILLED': 'closed',
918
+ 'CANCELED': 'canceled',
919
+ 'BEST_EFFORT_CANCELED': 'canceling',
920
+ };
921
+ return this.safeString(statuses, status, status);
922
+ }
923
+ parseOrderType(type) {
924
+ const types = {
925
+ 'LIMIT': 'LIMIT',
926
+ 'STOP_LIMIT': 'LIMIT',
927
+ 'TAKE_PROFIT_LIMIT': 'LIMIT',
928
+ 'MARKET': 'MARKET',
929
+ 'STOP_MARKET': 'MARKET',
930
+ 'TAKE_PROFIT_MARKET': 'MARKET',
931
+ 'TRAILING_STOP': 'MARKET',
932
+ };
933
+ return this.safeStringUpper(types, type, type);
934
+ }
935
+ /**
936
+ * @method
937
+ * @name dydx#fetchOrder
938
+ * @description fetches information on an order made by the user
939
+ * @see https://docs.dydx.xyz/indexer-client/http#get-order
940
+ * @param {string} id the order id
941
+ * @param {string} symbol unified symbol of the market the order was made in
942
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
943
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
944
+ */
945
+ async fetchOrder(id, symbol = undefined, params = {}) {
946
+ await this.loadMarkets();
947
+ const request = {
948
+ 'orderId': id,
949
+ };
950
+ const order = await this.indexerGetOrdersOrderId(this.extend(request, params));
951
+ return this.parseOrder(order);
952
+ }
953
+ /**
954
+ * @method
955
+ * @name dydx#fetchOrders
956
+ * @description fetches information on multiple orders made by the user
957
+ * @see https://docs.dydx.xyz/indexer-client/http#list-orders
958
+ * @param {string} symbol unified market symbol of the market orders were made in
959
+ * @param {int} [since] the earliest time in ms to fetch orders for
960
+ * @param {int} [limit] the maximum number of order structures to retrieve
961
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
962
+ * @param {string} [params.address] wallet address that made trades
963
+ * @param {string} [params.subAccountNumber] sub account number
964
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
965
+ */
966
+ async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
967
+ let userAddress = undefined;
968
+ let subAccountNumber = undefined;
969
+ [userAddress, params] = this.handlePublicAddress('fetchOrders', params);
970
+ [subAccountNumber, params] = this.handleOptionAndParams(params, 'fetchOrders', 'subAccountNumber', '0');
971
+ await this.loadMarkets();
972
+ const request = {
973
+ 'address': userAddress,
974
+ 'subaccountNumber': subAccountNumber,
975
+ };
976
+ let market = undefined;
977
+ if (symbol !== undefined) {
978
+ market = this.market(symbol);
979
+ request['ticker'] = market['id'];
980
+ }
981
+ if (limit !== undefined) {
982
+ request['limit'] = limit;
983
+ }
984
+ const response = await this.indexerGetOrders(this.extend(request, params));
985
+ //
986
+ // [
987
+ // {
988
+ // "id": "dad46410-3444-5566-a129-19a619300fb7",
989
+ // "subaccountId": "8586bcf6-1f58-5ec9-a0bc-e53db273e7b0",
990
+ // "clientId": "716238006",
991
+ // "clobPairId": "0",
992
+ // "side": "BUY",
993
+ // "size": "0.001",
994
+ // "totalFilled": "0.001",
995
+ // "price": "400000",
996
+ // "type": "LIMIT",
997
+ // "status": "FILLED",
998
+ // "timeInForce": "GTT",
999
+ // "reduceOnly": false,
1000
+ // "orderFlags": "64",
1001
+ // "goodTilBlockTime": "2025-07-28T12:07:33.000Z",
1002
+ // "createdAtHeight": "45058325",
1003
+ // "clientMetadata": "2",
1004
+ // "updatedAt": "2025-07-28T12:06:35.330Z",
1005
+ // "updatedAtHeight": "45058326",
1006
+ // "postOnly": false,
1007
+ // "ticker": "BTC-USD",
1008
+ // "subaccountNumber": 0
1009
+ // }
1010
+ // ]
1011
+ //
1012
+ return this.parseOrders(response, market, since, limit);
1013
+ }
1014
+ /**
1015
+ * @method
1016
+ * @name dydx#fetchOpenOrders
1017
+ * @description fetch all unfilled currently open orders
1018
+ * @see https://docs.dydx.xyz/indexer-client/http#list-orders
1019
+ * @param {string} symbol unified market symbol of the market orders were made in
1020
+ * @param {int} [since] the earliest time in ms to fetch orders for
1021
+ * @param {int} [limit] the maximum number of order structures to retrieve
1022
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1023
+ * @param {string} [params.address] wallet address that made trades
1024
+ * @param {string} [params.subAccountNumber] sub account number
1025
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1026
+ */
1027
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1028
+ const request = {
1029
+ 'status': 'OPEN', // ['OPEN', 'FILLED', 'CANCELED', 'BEST_EFFORT_CANCELED', 'UNTRIGGERED', 'BEST_EFFORT_OPENED']
1030
+ };
1031
+ return await this.fetchOrders(symbol, since, limit, this.extend(request, params));
1032
+ }
1033
+ /**
1034
+ * @method
1035
+ * @name dydx#fetchClosedOrders
1036
+ * @description fetches information on multiple closed orders made by the user
1037
+ * @see https://docs.dydx.xyz/indexer-client/http#list-orders
1038
+ * @param {string} symbol unified market symbol of the market orders were made in
1039
+ * @param {int} [since] the earliest time in ms to fetch orders for
1040
+ * @param {int} [limit] the maximum number of order structures to retrieve
1041
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1042
+ * @param {string} [params.address] wallet address that made trades
1043
+ * @param {string} [params.subAccountNumber] sub account number
1044
+ * @returns {Order[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1045
+ */
1046
+ async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1047
+ const request = {
1048
+ 'status': 'FILLED', // ['OPEN', 'FILLED', 'CANCELED', 'BEST_EFFORT_CANCELED', 'UNTRIGGERED', 'BEST_EFFORT_OPENED']
1049
+ };
1050
+ return await this.fetchOrders(symbol, since, limit, this.extend(request, params));
1051
+ }
1052
+ parsePosition(position, market = undefined) {
1053
+ //
1054
+ // {
1055
+ // "market": "BTC-USD",
1056
+ // "status": "OPEN",
1057
+ // "side": "SHORT",
1058
+ // "size": "-0.407",
1059
+ // "maxSize": "-0.009",
1060
+ // "entryPrice": "118692.04840909090909090909",
1061
+ // "exitPrice": "119526.565625",
1062
+ // "realizedPnl": "476.42665909090909090909088",
1063
+ // "unrealizedPnl": "-57.26681734000000000000037",
1064
+ // "createdAt": "2025-07-14T07:53:55.631Z",
1065
+ // "createdAtHeight": "44140908",
1066
+ // "closedAt": null,
1067
+ // "sumOpen": "0.44",
1068
+ // "sumClose": "0.032",
1069
+ // "netFunding": "503.13121",
1070
+ // "subaccountNumber": 0
1071
+ // }
1072
+ //
1073
+ const marketId = this.safeString(position, 'market');
1074
+ market = this.safeMarket(marketId, market);
1075
+ const symbol = market['symbol'];
1076
+ const side = this.safeStringLower(position, 'side');
1077
+ let quantity = this.safeString(position, 'size');
1078
+ if (side !== 'long') {
1079
+ quantity = Precise["default"].stringMul('-1', quantity);
1080
+ }
1081
+ const timestamp = this.parse8601(this.safeString(position, 'createdAt'));
1082
+ return this.safePosition({
1083
+ 'info': position,
1084
+ 'id': undefined,
1085
+ 'symbol': symbol,
1086
+ 'entryPrice': this.safeNumber(position, 'entryPrice'),
1087
+ 'markPrice': undefined,
1088
+ 'notional': undefined,
1089
+ 'collateral': undefined,
1090
+ 'unrealizedPnl': this.safeNumber(position, 'unrealizedPnl'),
1091
+ 'side': side,
1092
+ 'contracts': this.parseNumber(quantity),
1093
+ 'contractSize': undefined,
1094
+ 'timestamp': timestamp,
1095
+ 'datetime': this.iso8601(timestamp),
1096
+ 'hedged': undefined,
1097
+ 'maintenanceMargin': undefined,
1098
+ 'maintenanceMarginPercentage': undefined,
1099
+ 'initialMargin': undefined,
1100
+ 'initialMarginPercentage': undefined,
1101
+ 'leverage': undefined,
1102
+ 'liquidationPrice': undefined,
1103
+ 'marginRatio': undefined,
1104
+ 'marginMode': undefined,
1105
+ 'percentage': undefined,
1106
+ });
1107
+ }
1108
+ /**
1109
+ * @method
1110
+ * @name dydx#fetchPosition
1111
+ * @description fetch data on an open position
1112
+ * @see https://docs.dydx.xyz/indexer-client/http#list-positions
1113
+ * @param {string} symbol unified market symbol of the market the position is held in
1114
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1115
+ * @param {string} [params.address] wallet address that made trades
1116
+ * @param {string} [params.subAccountNumber] sub account number
1117
+ * @returns {object} a [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1118
+ */
1119
+ async fetchPosition(symbol, params = {}) {
1120
+ const positions = await this.fetchPositions([symbol], params);
1121
+ return this.safeDict(positions, 0, {});
1122
+ }
1123
+ /**
1124
+ * @method
1125
+ * @name dydx#fetchPositions
1126
+ * @description fetch all open positions
1127
+ * @see https://docs.dydx.xyz/indexer-client/http#list-positions
1128
+ * @param {string[]} [symbols] list of unified market symbols
1129
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1130
+ * @param {string} [params.address] wallet address that made trades
1131
+ * @param {string} [params.subAccountNumber] sub account number
1132
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/#/?id=position-structure}
1133
+ */
1134
+ async fetchPositions(symbols = undefined, params = {}) {
1135
+ let userAddress = undefined;
1136
+ let subAccountNumber = undefined;
1137
+ [userAddress, params] = this.handlePublicAddress('fetchPositions', params);
1138
+ [subAccountNumber, params] = this.handleOptionAndParams(params, 'fetchOrders', 'subAccountNumber', '0');
1139
+ await this.loadMarkets();
1140
+ const request = {
1141
+ 'address': userAddress,
1142
+ 'subaccountNumber': subAccountNumber,
1143
+ 'status': 'OPEN', // ['OPEN', 'CLOSED', 'LIQUIDATED']
1144
+ };
1145
+ const response = await this.indexerGetPerpetualPositions(this.extend(request, params));
1146
+ //
1147
+ // {
1148
+ // "positions": [
1149
+ // {
1150
+ // "market": "BTC-USD",
1151
+ // "status": "OPEN",
1152
+ // "side": "SHORT",
1153
+ // "size": "-0.407",
1154
+ // "maxSize": "-0.009",
1155
+ // "entryPrice": "118692.04840909090909090909",
1156
+ // "exitPrice": "119526.565625",
1157
+ // "realizedPnl": "476.42665909090909090909088",
1158
+ // "unrealizedPnl": "-57.26681734000000000000037",
1159
+ // "createdAt": "2025-07-14T07:53:55.631Z",
1160
+ // "createdAtHeight": "44140908",
1161
+ // "closedAt": null,
1162
+ // "sumOpen": "0.44",
1163
+ // "sumClose": "0.032",
1164
+ // "netFunding": "503.13121",
1165
+ // "subaccountNumber": 0
1166
+ // }
1167
+ // ]
1168
+ // }
1169
+ //
1170
+ const rows = this.safeList(response, 'positions', []);
1171
+ return this.parsePositions(rows, symbols);
1172
+ }
1173
+ hashMessage(message) {
1174
+ return this.hash(message, sha3.keccak_256, 'hex');
1175
+ }
1176
+ signHash(hash, privateKey) {
1177
+ const signature = crypto.ecdsa(hash.slice(-64), privateKey.slice(-64), secp256k1.secp256k1, undefined);
1178
+ const r = signature['r'];
1179
+ const s = signature['s'];
1180
+ return {
1181
+ 'r': r.padStart(64, '0'),
1182
+ 's': s.padStart(64, '0'),
1183
+ 'v': this.sum(27, signature['v']),
1184
+ };
1185
+ }
1186
+ signMessage(message, privateKey) {
1187
+ return this.signHash(this.hashMessage(message), privateKey.slice(-64));
1188
+ }
1189
+ signOnboardingAction() {
1190
+ const message = { 'action': 'dYdX Chain Onboarding' };
1191
+ const chainId = this.options['chainId'];
1192
+ const domain = {
1193
+ 'chainId': chainId,
1194
+ 'name': 'dYdX Chain',
1195
+ };
1196
+ const messageTypes = {
1197
+ 'dYdX': [
1198
+ { 'name': 'action', 'type': 'string' },
1199
+ ],
1200
+ };
1201
+ const msg = this.ethEncodeStructuredData(domain, messageTypes, message);
1202
+ if (this.privateKey === undefined || this.privateKey === '') {
1203
+ throw new errors.ArgumentsRequired(this.id + ' signOnboardingAction() requires a privateKey to be set.');
1204
+ }
1205
+ const signature = this.signMessage(msg, this.privateKey);
1206
+ return signature;
1207
+ }
1208
+ signDydxTx(privateKey, message, memo, chainId, account, authenticators, fee = undefined) {
1209
+ const [encodedTx, signDoc] = this.encodeDydxTxForSigning(message, memo, chainId, account, authenticators, fee);
1210
+ const signature = this.signHash(encodedTx, privateKey);
1211
+ return this.encodeDydxTxRaw(signDoc, signature['r'] + signature['s']);
1212
+ }
1213
+ retrieveCredentials() {
1214
+ let credentials = this.safeDict(this.options, 'dydxCredentials');
1215
+ if (credentials !== undefined) {
1216
+ return credentials;
1217
+ }
1218
+ let entropy = this.safeString(this.options, 'mnemonic');
1219
+ if (entropy === undefined) {
1220
+ const signature = this.signOnboardingAction();
1221
+ entropy = this.hashMessage(this.base16ToBinary(signature['r'] + signature['s']));
1222
+ }
1223
+ credentials = this.retrieveDydxCredentials(entropy);
1224
+ credentials['privateKey'] = this.binaryToBase16(credentials['privateKey']);
1225
+ credentials['publicKey'] = this.binaryToBase16(credentials['publicKey']);
1226
+ this.options['dydxCredentials'] = credentials;
1227
+ return credentials;
1228
+ }
1229
+ async fetchDydxAccount() {
1230
+ // required in js
1231
+ await this.loadDydxProtos();
1232
+ const dydxAccount = this.safeDict(this.options, 'dydxAccount');
1233
+ if (dydxAccount !== undefined) {
1234
+ return dydxAccount;
1235
+ }
1236
+ if (this.walletAddress === undefined) {
1237
+ throw new errors.ArgumentsRequired(this.id + ' fetchDydxAccount() requires the walletAddress to be set using the dydx chain address eg: dydx1cpb4tedmwq304c2kc9pwzjwq0sc6z2a4tasxrz');
1238
+ }
1239
+ if (!this.walletAddress.startsWith('dydx')) {
1240
+ throw new errors.ArgumentsRequired(this.id + ' fetchDydxAccount() requires a valid dydx chain address, starting with dydx, not the l1 address.');
1241
+ }
1242
+ const request = {
1243
+ 'dydxAddress': this.walletAddress,
1244
+ };
1245
+ //
1246
+ // {
1247
+ // "info": {
1248
+ // "address": "string",
1249
+ // "pub_key": {
1250
+ // "type_url": "string",
1251
+ // "key": "string"
1252
+ // },
1253
+ // "account_number": "string",
1254
+ // "sequence": "string"
1255
+ // }
1256
+ // }
1257
+ //
1258
+ const response = await this.nodeRestGetCosmosAuthV1beta1AccountInfoDydxAddress(request);
1259
+ const account = this.safeDict(response, 'info');
1260
+ account['pub_key'] = {
1261
+ // encode with binary key would fail in python
1262
+ 'key': account['pub_key']['key'],
1263
+ };
1264
+ this.options['dydxAccount'] = account;
1265
+ return account;
1266
+ }
1267
+ pow(n, m) {
1268
+ let r = Precise["default"].stringMul(n, '1');
1269
+ const c = this.parseToInt(m);
1270
+ // TODO: cap
1271
+ for (let i = 1; i < c; i++) {
1272
+ r = Precise["default"].stringMul(r, n);
1273
+ }
1274
+ return r;
1275
+ }
1276
+ createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
1277
+ const reduceOnly = this.safeBool2(params, 'reduceOnly', 'reduce_only', false);
1278
+ const orderType = type.toUpperCase();
1279
+ const market = this.market(symbol);
1280
+ const orderSide = side.toUpperCase();
1281
+ let subaccountId = 0;
1282
+ [subaccountId, params] = this.handleOptionAndParams(params, 'createOrder', 'subAccountId', subaccountId);
1283
+ const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
1284
+ const stopLossPrice = this.safeValue(params, 'stopLossPrice', triggerPrice);
1285
+ const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
1286
+ const isConditional = triggerPrice !== undefined || stopLossPrice !== undefined || takeProfitPrice !== undefined;
1287
+ const isMarket = orderType === 'MARKET';
1288
+ const timeInForce = this.safeStringUpper(params, 'timeInForce', 'GTT');
1289
+ const postOnly = this.isPostOnly(isMarket, undefined, params);
1290
+ const amountStr = this.amountToPrecision(symbol, amount);
1291
+ const priceStr = this.priceToPrecision(symbol, price);
1292
+ const marketInfo = this.safeDict(market, 'info');
1293
+ const atomicResolution = marketInfo['atomicResolution'];
1294
+ const quantumScale = this.pow('10', Precise["default"].stringNeg(atomicResolution));
1295
+ const quantums = Precise["default"].stringMul(amountStr, quantumScale);
1296
+ const quantumConversionExponent = marketInfo['quantumConversionExponent'];
1297
+ const priceScale = this.pow('10', Precise["default"].stringSub(Precise["default"].stringSub(atomicResolution, quantumConversionExponent), '-6'));
1298
+ const subticks = Precise["default"].stringMul(priceStr, priceScale);
1299
+ let clientMetadata = 0;
1300
+ let conditionalType = 0;
1301
+ let conditionalOrderTriggerSubticks = '0';
1302
+ let orderFlag = undefined;
1303
+ let timeInForceNumber = undefined;
1304
+ if (timeInForce === 'FOK') {
1305
+ throw new errors.InvalidOrder(this.id + ' timeInForce fok has been deprecated');
1306
+ }
1307
+ if (orderType === 'MARKET') {
1308
+ // short-term
1309
+ orderFlag = 0;
1310
+ clientMetadata = 1; // STOP_MARKET / TAKE_PROFIT_MARKET
1311
+ if (timeInForce !== undefined) {
1312
+ // default is ioc
1313
+ timeInForceNumber = 1;
1314
+ }
1315
+ }
1316
+ else if (orderType === 'LIMIT') {
1317
+ if (timeInForce === 'GTT') {
1318
+ // long-term
1319
+ orderFlag = 64;
1320
+ if (postOnly) {
1321
+ timeInForceNumber = 2;
1322
+ }
1323
+ else {
1324
+ timeInForceNumber = 0;
1325
+ }
1326
+ }
1327
+ else {
1328
+ orderFlag = 0;
1329
+ if (timeInForce === 'IOC') {
1330
+ timeInForceNumber = 1;
1331
+ }
1332
+ else {
1333
+ throw new errors.InvalidOrder('unexpected code path: timeInForce');
1334
+ }
1335
+ }
1336
+ }
1337
+ if (isConditional) {
1338
+ // conditional
1339
+ orderFlag = 32;
1340
+ if (stopLossPrice !== undefined) {
1341
+ conditionalType = 1;
1342
+ conditionalOrderTriggerSubticks = this.priceToPrecision(symbol, stopLossPrice);
1343
+ }
1344
+ else if (takeProfitPrice !== undefined) {
1345
+ conditionalType = 2;
1346
+ conditionalOrderTriggerSubticks = this.priceToPrecision(symbol, takeProfitPrice);
1347
+ }
1348
+ conditionalOrderTriggerSubticks = Precise["default"].stringMul(conditionalOrderTriggerSubticks, priceScale);
1349
+ }
1350
+ const latestBlockHeight = this.safeInteger(params, 'latestBlockHeight');
1351
+ let goodTillBlock = this.safeInteger(params, 'goodTillBlock');
1352
+ let goodTillBlockTime = undefined;
1353
+ let goodTillBlockTimeInSeconds = 2592000;
1354
+ [goodTillBlockTimeInSeconds, params] = this.handleOptionAndParams(params, 'createOrder', 'goodTillBlockTimeInSeconds', goodTillBlockTimeInSeconds); // default is 30 days
1355
+ if (orderFlag === 0) {
1356
+ if (goodTillBlock === undefined) {
1357
+ // short term order
1358
+ goodTillBlock = latestBlockHeight + 20;
1359
+ }
1360
+ }
1361
+ else {
1362
+ if (goodTillBlockTimeInSeconds === undefined) {
1363
+ throw new errors.ArgumentsRequired('goodTillBlockTimeInSeconds is required.');
1364
+ }
1365
+ goodTillBlockTime = this.seconds() + goodTillBlockTimeInSeconds;
1366
+ }
1367
+ const sideNumber = (orderSide === 'BUY') ? 1 : 2;
1368
+ const defaultClientOrderId = this.randNumber(9); // 2**32 - 1 is 10 digits, but it may overflow with 10
1369
+ const clientOrderId = this.safeInteger(params, 'clientOrderId', defaultClientOrderId);
1370
+ const orderPayload = {
1371
+ 'order': {
1372
+ 'orderId': {
1373
+ 'subaccountId': {
1374
+ 'owner': this.getWalletAddress(),
1375
+ 'number': subaccountId,
1376
+ },
1377
+ 'clientId': clientOrderId,
1378
+ 'orderFlags': orderFlag,
1379
+ 'clobPairId': marketInfo['clobPairId'],
1380
+ },
1381
+ 'side': sideNumber,
1382
+ 'quantums': this.toDydxLong(quantums),
1383
+ 'subticks': this.toDydxLong(subticks),
1384
+ 'goodTilBlock': goodTillBlock,
1385
+ 'goodTilBlockTime': goodTillBlockTime,
1386
+ 'timeInForce': timeInForceNumber,
1387
+ 'reduceOnly': reduceOnly,
1388
+ 'clientMetadata': clientMetadata,
1389
+ 'conditionType': conditionalType,
1390
+ 'conditionalOrderTriggerSubticks': this.toDydxLong(conditionalOrderTriggerSubticks),
1391
+ 'orderRouterAddress': this.safeString(this.options, 'routerAddress', 'dydx165sfn2k3vucvq7gklauy2r3agyjw4c3m60ascn'),
1392
+ },
1393
+ };
1394
+ const signingPayload = {
1395
+ 'typeUrl': '/dydxprotocol.clob.MsgPlaceOrder',
1396
+ 'value': orderPayload,
1397
+ };
1398
+ params = this.omit(params, ['reduceOnly', 'reduce_only', 'clientOrderId', 'postOnly', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLoss', 'takeProfit', 'latestBlockHeight', 'goodTillBlock', 'goodTillBlockTimeInSeconds', 'subaccountId']);
1399
+ const orderId = this.createOrderIdFromParts(this.getWalletAddress(), subaccountId, clientOrderId, orderFlag, marketInfo['clobPairId']);
1400
+ return [orderId, this.extend(signingPayload, params)];
1401
+ }
1402
+ createOrderIdFromParts(address, subAccountNumber, clientOrderId, orderFlags, clobPairId) {
1403
+ const nameSp = this.safeString(this.options, 'namespace', '0f9da948-a6fb-4c45-9edc-4685c3f3317d');
1404
+ const prefixAddress = address + '-' + subAccountNumber.toString();
1405
+ const prefix = this.uuid5(nameSp, prefixAddress);
1406
+ const orderInfo = prefix + '-' + this.numberToString(clientOrderId) + '-' + this.numberToString(clobPairId) + '-' + this.numberToString(orderFlags);
1407
+ return this.uuid5(nameSp, orderInfo);
1408
+ }
1409
+ async fetchLatestBlockHeight(params = {}) {
1410
+ const response = await this.nodeRpcGetAbciInfo(params);
1411
+ //
1412
+ // {
1413
+ // "jsonrpc": "2.0",
1414
+ // "id": -1,
1415
+ // "result": {
1416
+ // "response": {
1417
+ // "data": "dydxprotocol",
1418
+ // "version": "9.1.0-rc0",
1419
+ // "last_block_height": "49157714",
1420
+ // "last_block_app_hash": "9LHAcDDI5zmWiC6bGiiGtxuWPlKJV+/fTBZk/WQ/Y4U="
1421
+ // }
1422
+ // }
1423
+ // }
1424
+ //
1425
+ const result = this.safeDict(response, 'result');
1426
+ const info = this.safeDict(result, 'response');
1427
+ return this.safeInteger(info, 'last_block_height');
1428
+ }
1429
+ /**
1430
+ * @method
1431
+ * @name dydx#createOrder
1432
+ * @see https://docs.dydx.xyz/interaction/trading#place-an-order
1433
+ * @description create a trade order
1434
+ * @param {string} symbol unified symbol of the market to create an order in
1435
+ * @param {string} type 'market' or 'limit'
1436
+ * @param {string} side 'buy' or 'sell'
1437
+ * @param {float} amount how much of currency you want to trade in units of base currency
1438
+ * @param {float} [price] the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1439
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1440
+ * @param {string} [params.timeInForce] "GTT", "IOC", or "PO"
1441
+ * @param {float} [params.triggerPrice] The price a trigger order is triggered at
1442
+ * @param {float} [params.stopLossPrice] price for a stoploss order
1443
+ * @param {float} [params.takeProfitPrice] price for a takeprofit order
1444
+ * @param {string} [params.clientOrderId] a unique id for the order
1445
+ * @param {bool} [params.postOnly] true or false whether the order is post-only
1446
+ * @param {bool} [params.reduceOnly] true or false whether the order is reduce-only
1447
+ * @param {float} [params.goodTillBlock] expired block number for the order, required for market order and non limit GTT order, default value is latestBlockHeight + 20
1448
+ * @param {float} [params.goodTillBlockTimeInSeconds] expired time elapsed for the order, required for limit GTT order and conditional, default value is 30 days
1449
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1450
+ */
1451
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1452
+ await this.loadMarkets();
1453
+ const credentials = this.retrieveCredentials();
1454
+ const account = await this.fetchDydxAccount();
1455
+ const lastBlockHeight = await this.fetchLatestBlockHeight();
1456
+ // params['latestBlockHeight'] = lastBlockHeight;
1457
+ const newParams = this.extend(params, { 'latestBlockHeight': lastBlockHeight });
1458
+ const orderRequestRes = this.createOrderRequest(symbol, type, side, amount, price, newParams);
1459
+ const orderId = orderRequestRes[0];
1460
+ const orderRequest = orderRequestRes[1];
1461
+ const chainName = this.options['chainName'];
1462
+ const signedTx = this.signDydxTx(credentials['privateKey'], orderRequest, '', chainName, account, undefined);
1463
+ const request = {
1464
+ 'tx': signedTx,
1465
+ };
1466
+ // nodeRpcGetBroadcastTxAsync
1467
+ const response = await this.nodeRpcGetBroadcastTxSync(request);
1468
+ //
1469
+ // {
1470
+ // "jsonrpc": "2.0",
1471
+ // "id": -1,
1472
+ // "result": {
1473
+ // "code": 0,
1474
+ // "data": "",
1475
+ // "log": "[]",
1476
+ // "codespace": "",
1477
+ // "hash": "CBEDB0603E57E5CE21FA6954770A9403D2A81BED02E608C860356152D0AA1A81"
1478
+ // }
1479
+ // }
1480
+ //
1481
+ const result = this.safeDict(response, 'result');
1482
+ return this.safeOrder({
1483
+ 'info': result,
1484
+ 'id': orderId,
1485
+ 'clientOrderId': orderRequest['value']['order']['orderId']['clientId'],
1486
+ });
1487
+ }
1488
+ /**
1489
+ * @method
1490
+ * @name dydx#cancelOrder
1491
+ * @description cancels an open order
1492
+ * @see https://docs.dydx.xyz/interaction/trading/#cancel-an-order
1493
+ * @param {string} id it should be the clientOrderId in this case
1494
+ * @param {string} symbol unified symbol of the market the order was made in
1495
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1496
+ * @param {string} [params.clientOrderId] client order id used when creating the order
1497
+ * @param {boolean} [params.trigger] whether the order is a trigger/algo order
1498
+ * @param {float} [params.orderFlags] default is 64, orderFlags for the order, market order and non limit GTT order is 0, limit GTT order is 64 and conditional order is 32
1499
+ * @param {float} [params.goodTillBlock] expired block number for the order, required for market order and non limit GTT order (orderFlags = 0), default value is latestBlockHeight + 20
1500
+ * @param {float} [params.goodTillBlockTimeInSeconds] expired time elapsed for the order, required for limit GTT order and conditional (orderFlagss > 0), default value is 30 days
1501
+ * @param {int} [params.subAccountId] sub account id, default is 0
1502
+ * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1503
+ */
1504
+ async cancelOrder(id, symbol = undefined, params = {}) {
1505
+ const isTrigger = this.safeBool2(params, 'trigger', 'stop', false);
1506
+ params = this.omit(params, ['trigger', 'stop']);
1507
+ if (!isTrigger && (symbol === undefined)) {
1508
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires a symbol argument');
1509
+ }
1510
+ await this.loadMarkets();
1511
+ const market = this.market(symbol);
1512
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'clientId', id);
1513
+ if (clientOrderId === undefined) {
1514
+ throw new errors.ArgumentsRequired(this.id + ' cancelOrder() requires a clientOrderId parameter, cancelling using id is not currently supported.');
1515
+ }
1516
+ const idString = id.toString();
1517
+ if (id !== undefined && idString.indexOf('-') > -1) {
1518
+ throw new errors.NotSupported(this.id + ' cancelOrder() cancelling using id is not currently supported, please use provide the clientOrderId parameter.');
1519
+ }
1520
+ let goodTillBlock = this.safeInteger(params, 'goodTillBlock');
1521
+ let goodTillBlockTimeInSeconds = 2592000;
1522
+ [goodTillBlockTimeInSeconds, params] = this.handleOptionAndParams(params, 'cancelOrder', 'goodTillBlockTimeInSeconds', goodTillBlockTimeInSeconds); // default is 30 days
1523
+ let goodTillBlockTime = undefined;
1524
+ const defaultOrderFlags = (isTrigger) ? 32 : 64;
1525
+ const orderFlags = this.safeInteger(params, 'orderFlags', defaultOrderFlags);
1526
+ let subAccountId = 0;
1527
+ [subAccountId, params] = this.handleOptionAndParams(params, 'cancelOrder', 'subAccountId', subAccountId);
1528
+ params = this.omit(params, ['clientOrderId', 'orderFlags', 'goodTillBlock', 'goodTillBlockTime', 'goodTillBlockTimeInSeconds', 'subaccountId', 'clientId']);
1529
+ if (orderFlags !== 0 && orderFlags !== 64 && orderFlags !== 32) {
1530
+ throw new errors.InvalidOrder(this.id + ' invalid orderFlags, allowed values are (0, 64, 32).');
1531
+ }
1532
+ if (orderFlags > 0) {
1533
+ if (goodTillBlockTimeInSeconds === undefined) {
1534
+ throw new errors.ArgumentsRequired(this.id + ' goodTillBlockTimeInSeconds is required in params for long term or conditional order.');
1535
+ }
1536
+ if (goodTillBlock !== undefined && goodTillBlock > 0) {
1537
+ throw new errors.InvalidOrder(this.id + ' goodTillBlock should be 0 for long term or conditional order.');
1538
+ }
1539
+ goodTillBlockTime = this.seconds() + goodTillBlockTimeInSeconds;
1540
+ }
1541
+ else {
1542
+ if (goodTillBlock === undefined) {
1543
+ const latestBlockHeight = await this.fetchLatestBlockHeight();
1544
+ goodTillBlock = latestBlockHeight + 20;
1545
+ }
1546
+ }
1547
+ const credentials = this.retrieveCredentials();
1548
+ const account = await this.fetchDydxAccount();
1549
+ const cancelPayload = {
1550
+ 'orderId': {
1551
+ 'subaccountId': {
1552
+ 'owner': this.getWalletAddress(),
1553
+ 'number': subAccountId,
1554
+ },
1555
+ 'clientId': clientOrderId,
1556
+ 'orderFlags': orderFlags,
1557
+ 'clobPairId': market['info']['clobPairId'],
1558
+ },
1559
+ 'goodTilBlock': goodTillBlock,
1560
+ 'goodTilBlockTime': goodTillBlockTime,
1561
+ };
1562
+ const signingPayload = {
1563
+ 'typeUrl': '/dydxprotocol.clob.MsgCancelOrder',
1564
+ 'value': cancelPayload,
1565
+ };
1566
+ const chainName = this.options['chainName'];
1567
+ const signedTx = this.signDydxTx(credentials['privateKey'], signingPayload, '', chainName, account, undefined);
1568
+ const request = {
1569
+ 'tx': signedTx,
1570
+ };
1571
+ // nodeRpcGetBroadcastTxAsync
1572
+ const response = await this.nodeRpcGetBroadcastTxSync(request);
1573
+ //
1574
+ // {
1575
+ // "jsonrpc": "2.0",
1576
+ // "id": -1,
1577
+ // "result": {
1578
+ // "code": 0,
1579
+ // "data": "",
1580
+ // "log": "[]",
1581
+ // "codespace": "",
1582
+ // "hash": "CBEDB0603E57E5CE21FA6954770A9403D2A81BED02E608C860356152D0AA1A81"
1583
+ // }
1584
+ // }
1585
+ //
1586
+ const result = this.safeDict(response, 'result');
1587
+ return this.safeOrder({
1588
+ 'info': result,
1589
+ });
1590
+ }
1591
+ /**
1592
+ * @method
1593
+ * @name dydx#cancelOrders
1594
+ * @description cancel multiple orders
1595
+ * @param {string[]} ids order ids
1596
+ * @param {string} [symbol] unified market symbol
1597
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1598
+ * @param {string[]} [params.clientOrderIds] max length 10 e.g. ["my_id_1","my_id_2"], encode the double quotes. No space after comma
1599
+ * @param {int} [params.subAccountId] sub account id, default is 0
1600
+ * @returns {object} an list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
1601
+ */
1602
+ async cancelOrders(ids, symbol = undefined, params = {}) {
1603
+ await this.loadMarkets();
1604
+ const market = this.market(symbol);
1605
+ const clientOrderIds = this.safeList(params, 'clientOrderIds');
1606
+ if (!clientOrderIds) {
1607
+ throw new errors.NotSupported(this.id + ' cancelOrders only support clientOrderIds.');
1608
+ }
1609
+ let subAccountId = 0;
1610
+ [subAccountId, params] = this.handleOptionAndParams(params, 'cancelOrders', 'subAccountId', subAccountId);
1611
+ let goodTillBlock = this.safeInteger(params, 'goodTillBlock');
1612
+ if (goodTillBlock === undefined) {
1613
+ const latestBlockHeight = await this.fetchLatestBlockHeight();
1614
+ goodTillBlock = latestBlockHeight + 20;
1615
+ }
1616
+ params = this.omit(params, ['clientOrderIds', 'goodTillBlock', 'subaccountId']);
1617
+ const credentials = this.retrieveCredentials();
1618
+ const account = await this.fetchDydxAccount();
1619
+ const cancelOrders = {
1620
+ 'clientIds': clientOrderIds,
1621
+ 'clobPairId': market['info']['clobPairId'],
1622
+ };
1623
+ const cancelPayload = {
1624
+ 'subaccountId': {
1625
+ 'owner': this.getWalletAddress(),
1626
+ 'number': subAccountId,
1627
+ },
1628
+ 'shortTermCancels': [cancelOrders],
1629
+ 'goodTilBlock': goodTillBlock,
1630
+ };
1631
+ const signingPayload = {
1632
+ 'typeUrl': '/dydxprotocol.clob.MsgBatchCancel',
1633
+ 'value': cancelPayload,
1634
+ };
1635
+ const chainName = this.options['chainName'];
1636
+ const signedTx = this.signDydxTx(credentials['privateKey'], signingPayload, '', chainName, account, undefined);
1637
+ const request = {
1638
+ 'tx': signedTx,
1639
+ };
1640
+ // nodeRpcGetBroadcastTxAsync
1641
+ const response = await this.nodeRpcGetBroadcastTxSync(request);
1642
+ //
1643
+ // {
1644
+ // "jsonrpc": "2.0",
1645
+ // "id": -1,
1646
+ // "result": {
1647
+ // "code": 0,
1648
+ // "data": "",
1649
+ // "log": "[]",
1650
+ // "codespace": "",
1651
+ // "hash": "CBEDB0603E57E5CE21FA6954770A9403D2A81BED02E608C860356152D0AA1A81"
1652
+ // }
1653
+ // }
1654
+ //
1655
+ const result = this.safeDict(response, 'result');
1656
+ return [this.safeOrder({
1657
+ 'info': result,
1658
+ })];
1659
+ }
1660
+ /**
1661
+ * @method
1662
+ * @name dydx#fetchOrderBook
1663
+ * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
1664
+ * @see https://docs.dydx.xyz/indexer-client/http#get-perpetual-market-orderbook
1665
+ * @param {string} symbol unified symbol of the market to fetch the order book for
1666
+ * @param {int} [limit] the maximum amount of order book entries to return
1667
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1668
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
1669
+ */
1670
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
1671
+ await this.loadMarkets();
1672
+ const market = this.market(symbol);
1673
+ const request = {
1674
+ 'market': market['id'],
1675
+ };
1676
+ const response = await this.indexerGetOrderbooksPerpetualMarketMarket(this.extend(request, params));
1677
+ //
1678
+ // {
1679
+ // "bids": [
1680
+ // {
1681
+ // "price": "118267",
1682
+ // "size": "0.3182"
1683
+ // }
1684
+ // ],
1685
+ // "asks": [
1686
+ // {
1687
+ // "price": "118485",
1688
+ // "size": "0.0001"
1689
+ // }
1690
+ // ]
1691
+ // }
1692
+ //
1693
+ return this.parseOrderBook(response, market['symbol'], undefined, 'bids', 'asks', 'price', 'size');
1694
+ }
1695
+ parseLedgerEntry(item, currency = undefined) {
1696
+ //
1697
+ // {
1698
+ // "id": "6a6075bc-7183-5fd9-bc9d-894e238aa527",
1699
+ // "sender": {
1700
+ // "address": "dydx14zzueazeh0hj67cghhf9jypslcf9sh2n5k6art",
1701
+ // "subaccountNumber": 0
1702
+ // },
1703
+ // "recipient": {
1704
+ // "address": "dydx1slanxj8x9ntk9knwa6cvfv2tzlsq5gk3dshml0",
1705
+ // "subaccountNumber": 1
1706
+ // },
1707
+ // "size": "0.000001",
1708
+ // "createdAt": "2025-07-29T09:43:02.105Z",
1709
+ // "createdAtHeight": "45116125",
1710
+ // "symbol": "USDC",
1711
+ // "type": "TRANSFER_OUT",
1712
+ // "transactionHash": "92B4744BA1B783CF37C79A50BEBC47FFD59C8D5197D62A8485D3DCCE9AF220AF"
1713
+ // }
1714
+ //
1715
+ const currencyId = this.safeString(item, 'symbol');
1716
+ const code = this.safeCurrencyCode(currencyId, currency);
1717
+ currency = this.safeCurrency(currencyId, currency);
1718
+ const type = this.safeStringUpper(item, 'type');
1719
+ let direction = undefined;
1720
+ if (type !== undefined) {
1721
+ if (type === 'TRANSFER_IN' || type === 'DEPOSIT') {
1722
+ direction = 'in';
1723
+ }
1724
+ else if (type === 'TRANSFER_OUT' || type === 'WITHDRAWAL') {
1725
+ direction = 'out';
1726
+ }
1727
+ }
1728
+ const amount = this.safeString(item, 'size');
1729
+ const timestamp = this.parse8601(this.safeString(item, 'createdAt'));
1730
+ const sender = this.safeDict(item, 'sender');
1731
+ const recipient = this.safeDict(item, 'recipient');
1732
+ return this.safeLedgerEntry({
1733
+ 'info': item,
1734
+ 'id': this.safeString(item, 'id'),
1735
+ 'direction': direction,
1736
+ 'account': this.safeString(sender, 'address'),
1737
+ 'referenceAccount': this.safeString(recipient, 'address'),
1738
+ 'referenceId': this.safeString(item, 'transactionHash'),
1739
+ 'type': this.parseLedgerEntryType(type),
1740
+ 'currency': code,
1741
+ 'amount': this.parseNumber(amount),
1742
+ 'timestamp': timestamp,
1743
+ 'datetime': this.iso8601(timestamp),
1744
+ 'before': undefined,
1745
+ 'after': undefined,
1746
+ 'status': undefined,
1747
+ 'fee': undefined,
1748
+ }, currency);
1749
+ }
1750
+ parseLedgerEntryType(type) {
1751
+ const ledgerType = {
1752
+ 'TRANSFER_IN': 'transfer',
1753
+ 'TRANSFER_OUT': 'transfer',
1754
+ 'DEPOSIT': 'deposit',
1755
+ 'WITHDRAWAL': 'withdrawal',
1756
+ };
1757
+ return this.safeString(ledgerType, type, type);
1758
+ }
1759
+ /**
1760
+ * @method
1761
+ * @name dydx#fetchLedger
1762
+ * @description fetch the history of changes, actions done by the user or operations that altered balance of the user
1763
+ * @see https://docs.dydx.xyz/indexer-client/http#get-transfers
1764
+ * @param {string} [code] unified currency code, default is undefined
1765
+ * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
1766
+ * @param {int} [limit] max number of ledger entries to return, default is undefined
1767
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1768
+ * @param {string} [params.address] wallet address that made trades
1769
+ * @param {string} [params.subAccountNumber] sub account number
1770
+ * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger}
1771
+ */
1772
+ async fetchLedger(code = undefined, since = undefined, limit = undefined, params = {}) {
1773
+ await this.loadMarkets();
1774
+ let currency = undefined;
1775
+ if (code !== undefined) {
1776
+ currency = this.currency(code);
1777
+ }
1778
+ const response = await this.fetchTransactionsHelper(code, since, limit, this.extend(params, { 'methodName': 'fetchLedger' }));
1779
+ return this.parseLedger(response, currency, since, limit);
1780
+ }
1781
+ async estimateTxFee(message, memo, account) {
1782
+ const txBytes = this.encodeDydxTxForSimulation(message, memo, account['sequence'], account['pub_key']);
1783
+ const request = {
1784
+ 'txBytes': txBytes,
1785
+ };
1786
+ const response = await this.nodeRestPostCosmosTxV1beta1Simulate(request);
1787
+ //
1788
+ // {
1789
+ // gas_info: { gas_wanted: '18446744073709551615', gas_used: '86055' },
1790
+ // result: {
1791
+ // ...
1792
+ // }
1793
+ // }
1794
+ //
1795
+ const gasInfo = this.safeDict(response, 'gas_info');
1796
+ if (gasInfo === undefined) {
1797
+ throw new errors.ExchangeError(this.id + ' failed to simulate transaction.');
1798
+ }
1799
+ const gasUsed = this.safeString(gasInfo, 'gas_used');
1800
+ if (gasUsed === undefined) {
1801
+ throw new errors.ExchangeError(this.id + ' failed to simulate transaction.');
1802
+ }
1803
+ const defaultFeeDenom = this.safeString(this.options, 'defaultFeeDenom');
1804
+ const defaultFeeMultiplier = this.safeString(this.options, 'defaultFeeMultiplier');
1805
+ const feeDenom = this.safeDict(this.options, 'feeDenom');
1806
+ let gasPrice = undefined;
1807
+ let denom = undefined;
1808
+ if (defaultFeeDenom === 'uusdc') {
1809
+ gasPrice = feeDenom['USDC_GAS_PRICE'];
1810
+ denom = feeDenom['USDC_DENOM'];
1811
+ }
1812
+ else {
1813
+ gasPrice = feeDenom['CHAINTOKEN_GAS_PRICE'];
1814
+ denom = feeDenom['CHAINTOKEN_DENOM'];
1815
+ }
1816
+ const gasLimit = Math.ceil(this.parseToNumeric(Precise["default"].stringMul(gasUsed, defaultFeeMultiplier)));
1817
+ let feeAmount = Precise["default"].stringMul(this.numberToString(gasLimit), gasPrice);
1818
+ if (feeAmount.indexOf('.') >= 0) {
1819
+ feeAmount = this.numberToString(Math.ceil(this.parseToNumeric(feeAmount)));
1820
+ }
1821
+ const feeObj = {
1822
+ 'amount': feeAmount,
1823
+ 'denom': denom,
1824
+ };
1825
+ return {
1826
+ 'amount': [feeObj],
1827
+ 'gasLimit': gasLimit,
1828
+ };
1829
+ }
1830
+ /**
1831
+ * @method
1832
+ * @name dydx#transfer
1833
+ * @description transfer currency internally between wallets on the same account
1834
+ * @param {string} code unified currency code
1835
+ * @param {float} amount amount to transfer
1836
+ * @param {string} fromAccount account to transfer from *main, subaccount*
1837
+ * @param {string} toAccount account to transfer to *subaccount, address*
1838
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1839
+ * @param {string} [params.vaultAddress] the vault address for order
1840
+ * @returns {object} a [transfer structure]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1841
+ */
1842
+ async transfer(code, amount, fromAccount, toAccount, params = {}) {
1843
+ if (code !== 'USDC') {
1844
+ throw new errors.NotSupported(this.id + ' transfer() only support USDC');
1845
+ }
1846
+ await this.loadMarkets();
1847
+ const fromSubaccountId = this.safeInteger(params, 'fromSubaccountId');
1848
+ const toSubaccountId = this.safeInteger(params, 'toSubaccountId');
1849
+ if (fromAccount !== 'main') {
1850
+ // throw error if from subaccount id is undefind
1851
+ if (fromAccount === undefined) {
1852
+ throw new errors.NotSupported(this.id + ' transfer only support main > subaccount and subaccount <> subaccount.');
1853
+ }
1854
+ if (fromSubaccountId === undefined || toSubaccountId === undefined) {
1855
+ throw new errors.ArgumentsRequired(this.id + ' transfer requires fromSubaccountId and toSubaccountId.');
1856
+ }
1857
+ }
1858
+ params = this.omit(params, ['fromSubaccountId', 'toSubaccountId']);
1859
+ const credentials = this.retrieveCredentials();
1860
+ const account = await this.fetchDydxAccount();
1861
+ const usd = this.parseToInt(Precise["default"].stringMul(this.numberToString(amount), '1000000'));
1862
+ let payload = undefined;
1863
+ let signingPayload = undefined;
1864
+ if (fromAccount === 'main') {
1865
+ // deposit to subaccount
1866
+ if (toSubaccountId === undefined) {
1867
+ throw new errors.ArgumentsRequired(this.id + ' transfer() requeire toSubaccoutnId.');
1868
+ }
1869
+ payload = {
1870
+ 'sender': this.getWalletAddress(),
1871
+ 'recipient': {
1872
+ 'owner': this.getWalletAddress(),
1873
+ 'number': toSubaccountId,
1874
+ },
1875
+ 'assetId': 0,
1876
+ 'quantums': usd,
1877
+ };
1878
+ signingPayload = {
1879
+ 'typeUrl': '/dydxprotocol.sending.MsgDepositToSubaccount',
1880
+ 'value': payload,
1881
+ };
1882
+ }
1883
+ else {
1884
+ payload = {
1885
+ 'transfer': {
1886
+ 'sender': {
1887
+ 'owner': fromAccount,
1888
+ 'number': fromSubaccountId,
1889
+ },
1890
+ 'recipient': {
1891
+ 'owner': toAccount,
1892
+ 'number': toSubaccountId,
1893
+ },
1894
+ 'assetId': 0,
1895
+ 'amount': usd,
1896
+ },
1897
+ };
1898
+ signingPayload = {
1899
+ 'typeUrl': '/dydxprotocol.sending.MsgCreateTransfer',
1900
+ 'value': payload,
1901
+ };
1902
+ }
1903
+ const txFee = await this.estimateTxFee(signingPayload, '', account);
1904
+ const chainName = this.options['chainName'];
1905
+ const signedTx = this.signDydxTx(credentials['privateKey'], signingPayload, '', chainName, account, undefined, txFee);
1906
+ const request = {
1907
+ 'tx': signedTx,
1908
+ };
1909
+ // nodeRpcGetBroadcastTxAsync
1910
+ const response = await this.nodeRpcGetBroadcastTxSync(request);
1911
+ //
1912
+ // {
1913
+ // "jsonrpc": "2.0",
1914
+ // "id": -1,
1915
+ // "result": {
1916
+ // "code": 0,
1917
+ // "data": "",
1918
+ // "log": "[]",
1919
+ // "codespace": "",
1920
+ // "hash": "CBEDB0603E57E5CE21FA6954770A9403D2A81BED02E608C860356152D0AA1A81"
1921
+ // }
1922
+ // }
1923
+ //
1924
+ return this.parseTransfer(response);
1925
+ }
1926
+ parseTransfer(transfer, currency = undefined) {
1927
+ //
1928
+ // {
1929
+ // "id": "6a6075bc-7183-5fd9-bc9d-894e238aa527",
1930
+ // "sender": {
1931
+ // "address": "dydx14zzueazeh0hj67cghhf9jypslcf9sh2n5k6art",
1932
+ // "subaccountNumber": 0
1933
+ // },
1934
+ // "recipient": {
1935
+ // "address": "dydx1slanxj8x9ntk9knwa6cvfv2tzlsq5gk3dshml0",
1936
+ // "subaccountNumber": 1
1937
+ // },
1938
+ // "size": "0.000001",
1939
+ // "createdAt": "2025-07-29T09:43:02.105Z",
1940
+ // "createdAtHeight": "45116125",
1941
+ // "symbol": "USDC",
1942
+ // "type": "TRANSFER_OUT",
1943
+ // "transactionHash": "92B4744BA1B783CF37C79A50BEBC47FFD59C8D5197D62A8485D3DCCE9AF220AF"
1944
+ // }
1945
+ //
1946
+ const id = this.safeString(transfer, 'id');
1947
+ const currencyId = this.safeString(transfer, 'symbol');
1948
+ const code = this.safeCurrencyCode(currencyId, currency);
1949
+ const amount = this.safeNumber(transfer, 'size');
1950
+ const sender = this.safeDict(transfer, 'sender');
1951
+ const recipient = this.safeDict(transfer, 'recipient');
1952
+ const fromAccount = this.safeString(sender, 'address');
1953
+ const toAccount = this.safeString(recipient, 'address');
1954
+ const timestamp = this.parse8601(this.safeString(transfer, 'createdAt'));
1955
+ return {
1956
+ 'info': transfer,
1957
+ 'id': id,
1958
+ 'timestamp': timestamp,
1959
+ 'datetime': this.iso8601(timestamp),
1960
+ 'currency': code,
1961
+ 'amount': amount,
1962
+ 'fromAccount': fromAccount,
1963
+ 'toAccount': toAccount,
1964
+ 'status': undefined,
1965
+ };
1966
+ }
1967
+ /**
1968
+ * @method
1969
+ * @name dydx#fetchTransfers
1970
+ * @description fetch a history of internal transfers made on an account
1971
+ * @see https://docs.dydx.xyz/indexer-client/http#get-transfers
1972
+ * @param {string} code unified currency code of the currency transferred
1973
+ * @param {int} [since] the earliest time in ms to fetch transfers for
1974
+ * @param {int} [limit] the maximum number of transfers structures to retrieve
1975
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1976
+ * @param {string} [params.address] wallet address that made trades
1977
+ * @param {string} [params.subAccountNumber] sub account number
1978
+ * @returns {object[]} a list of [transfer structures]{@link https://docs.ccxt.com/#/?id=transfer-structure}
1979
+ */
1980
+ async fetchTransfers(code = undefined, since = undefined, limit = undefined, params = {}) {
1981
+ await this.loadMarkets();
1982
+ let currency = undefined;
1983
+ if (code !== undefined) {
1984
+ currency = this.currency(code);
1985
+ }
1986
+ const response = await this.fetchTransactionsHelper(code, since, limit, this.extend(params, { 'methodName': 'fetchTransfers' }));
1987
+ const transferIn = this.filterBy(response, 'type', 'TRANSFER_IN');
1988
+ const transferOut = this.filterBy(response, 'type', 'TRANSFER_OUT');
1989
+ const rows = this.arrayConcat(transferIn, transferOut);
1990
+ return this.parseTransfers(rows, currency, since, limit);
1991
+ }
1992
+ parseTransaction(transaction, currency = undefined) {
1993
+ //
1994
+ // {
1995
+ // "id": "6a6075bc-7183-5fd9-bc9d-894e238aa527",
1996
+ // "sender": {
1997
+ // "address": "dydx14zzueazeh0hj67cghhf9jypslcf9sh2n5k6art",
1998
+ // "subaccountNumber": 0
1999
+ // },
2000
+ // "recipient": {
2001
+ // "address": "dydx1slanxj8x9ntk9knwa6cvfv2tzlsq5gk3dshml0",
2002
+ // "subaccountNumber": 1
2003
+ // },
2004
+ // "size": "0.000001",
2005
+ // "createdAt": "2025-07-29T09:43:02.105Z",
2006
+ // "createdAtHeight": "45116125",
2007
+ // "symbol": "USDC",
2008
+ // "type": "TRANSFER_OUT",
2009
+ // "transactionHash": "92B4744BA1B783CF37C79A50BEBC47FFD59C8D5197D62A8485D3DCCE9AF220AF"
2010
+ // }
2011
+ //
2012
+ const id = this.safeString(transaction, 'id');
2013
+ const sender = this.safeDict(transaction, 'sender');
2014
+ const recipient = this.safeDict(transaction, 'recipient');
2015
+ const addressTo = this.safeString(recipient, 'address');
2016
+ const addressFrom = this.safeString(sender, 'address');
2017
+ const txid = this.safeString(transaction, 'transactionHash');
2018
+ const currencyId = this.safeString(transaction, 'symbol');
2019
+ const code = this.safeCurrencyCode(currencyId, currency);
2020
+ const timestamp = this.parse8601(this.safeString(transaction, 'createdAt'));
2021
+ const amount = this.safeNumber(transaction, 'size');
2022
+ return {
2023
+ 'info': transaction,
2024
+ 'id': id,
2025
+ 'txid': txid,
2026
+ 'timestamp': timestamp,
2027
+ 'datetime': this.iso8601(timestamp),
2028
+ 'network': undefined,
2029
+ 'address': addressTo,
2030
+ 'addressTo': addressTo,
2031
+ 'addressFrom': addressFrom,
2032
+ 'tag': undefined,
2033
+ 'tagTo': undefined,
2034
+ 'tagFrom': undefined,
2035
+ 'type': this.safeStringLower(transaction, 'type'),
2036
+ 'amount': amount,
2037
+ 'currency': code,
2038
+ 'status': undefined,
2039
+ 'updated': undefined,
2040
+ 'internal': undefined,
2041
+ 'comment': undefined,
2042
+ 'fee': undefined,
2043
+ };
2044
+ }
2045
+ /**
2046
+ * @method
2047
+ * @name dydx#withdraw
2048
+ * @description make a withdrawal
2049
+ * @param {string} code unified currency code
2050
+ * @param {float} amount the amount to withdraw
2051
+ * @param {string} address the address to withdraw to
2052
+ * @param {string} tag
2053
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2054
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2055
+ */
2056
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
2057
+ if (code !== 'USDC') {
2058
+ throw new errors.NotSupported(this.id + ' withdraw() only support USDC');
2059
+ }
2060
+ await this.loadMarkets();
2061
+ this.checkAddress(address);
2062
+ const subaccountId = this.safeInteger(params, 'subaccountId');
2063
+ if (subaccountId === undefined) {
2064
+ throw new errors.ArgumentsRequired(this.id + ' withdraw requires subaccountId.');
2065
+ }
2066
+ params = this.omit(params, ['subaccountId']);
2067
+ const currency = this.currency(code);
2068
+ const credentials = this.retrieveCredentials();
2069
+ const account = await this.fetchDydxAccount();
2070
+ const usd = this.parseToInt(Precise["default"].stringMul(this.numberToString(amount), '1000000'));
2071
+ const payload = {
2072
+ 'sender': {
2073
+ 'owner': this.getWalletAddress(),
2074
+ 'number': subaccountId,
2075
+ },
2076
+ 'recipient': address,
2077
+ 'assetId': 0,
2078
+ 'quantums': usd,
2079
+ };
2080
+ const signingPayload = {
2081
+ 'typeUrl': '/dydxprotocol.sending.MsgWithdrawFromSubaccount',
2082
+ 'value': payload,
2083
+ };
2084
+ const txFee = await this.estimateTxFee(signingPayload, tag, account);
2085
+ const chainName = this.options['chainName'];
2086
+ const signedTx = this.signDydxTx(credentials['privateKey'], signingPayload, tag, chainName, account, undefined, txFee);
2087
+ const request = {
2088
+ 'tx': signedTx,
2089
+ };
2090
+ // nodeRpcGetBroadcastTxAsync
2091
+ const response = await this.nodeRpcGetBroadcastTxSync(request);
2092
+ //
2093
+ // {
2094
+ // "jsonrpc": "2.0",
2095
+ // "id": -1,
2096
+ // "result": {
2097
+ // "code": 0,
2098
+ // "data": "",
2099
+ // "log": "[]",
2100
+ // "codespace": "",
2101
+ // "hash": "CBEDB0603E57E5CE21FA6954770A9403D2A81BED02E608C860356152D0AA1A81"
2102
+ // }
2103
+ // }
2104
+ //
2105
+ const data = this.safeDict(response, 'result', {});
2106
+ return this.parseTransaction(data, currency);
2107
+ }
2108
+ /**
2109
+ * @method
2110
+ * @name dydx#fetchWithdrawals
2111
+ * @description fetch all withdrawals made from an account
2112
+ * @see https://docs.dydx.xyz/indexer-client/http#get-transfers
2113
+ * @param {string} code unified currency code
2114
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
2115
+ * @param {int} [limit] the maximum number of withdrawals structures to retrieve
2116
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2117
+ * @param {string} [params.address] wallet address that made trades
2118
+ * @param {string} [params.subAccountNumber] sub account number
2119
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2120
+ */
2121
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2122
+ await this.loadMarkets();
2123
+ let currency = undefined;
2124
+ if (code !== undefined) {
2125
+ currency = this.currency(code);
2126
+ }
2127
+ const response = await this.fetchTransactionsHelper(code, since, limit, this.extend(params, { 'methodName': 'fetchWithdrawals' }));
2128
+ const rows = this.filterBy(response, 'type', 'WITHDRAWAL');
2129
+ return this.parseTransactions(rows, currency, since, limit);
2130
+ }
2131
+ /**
2132
+ * @method
2133
+ * @name dydx#fetchDeposits
2134
+ * @description fetch all deposits made to an account
2135
+ * @see https://docs.dydx.xyz/indexer-client/http#get-transfers
2136
+ * @param {string} code unified currency code
2137
+ * @param {int} [since] the earliest time in ms to fetch deposits for
2138
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
2139
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2140
+ * @param {string} [params.address] wallet address that made trades
2141
+ * @param {string} [params.subAccountNumber] sub account number
2142
+ * @returns {object[]} a list of [transaction structures]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2143
+ */
2144
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2145
+ await this.loadMarkets();
2146
+ let currency = undefined;
2147
+ if (code !== undefined) {
2148
+ currency = this.currency(code);
2149
+ }
2150
+ const response = await this.fetchTransactionsHelper(code, since, limit, this.extend(params, { 'methodName': 'fetchDeposits' }));
2151
+ const rows = this.filterBy(response, 'type', 'DEPOSIT');
2152
+ return this.parseTransactions(rows, currency, since, limit);
2153
+ }
2154
+ /**
2155
+ * @method
2156
+ * @name dydx#fetchDepositsWithdrawals
2157
+ * @description fetch history of deposits and withdrawals
2158
+ * @see https://docs.dydx.xyz/indexer-client/http#get-transfers
2159
+ * @param {string} [code] unified currency code for the currency of the deposit/withdrawals, default is undefined
2160
+ * @param {int} [since] timestamp in ms of the earliest deposit/withdrawal, default is undefined
2161
+ * @param {int} [limit] max number of deposit/withdrawals to return, default is undefined
2162
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2163
+ * @param {string} [params.address] wallet address that made trades
2164
+ * @param {string} [params.subAccountNumber] sub account number
2165
+ * @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
2166
+ */
2167
+ async fetchDepositsWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2168
+ await this.loadMarkets();
2169
+ let currency = undefined;
2170
+ if (code !== undefined) {
2171
+ currency = this.currency(code);
2172
+ }
2173
+ const response = await this.fetchTransactionsHelper(code, since, limit, this.extend(params, { 'methodName': 'fetchDepositsWithdrawals' }));
2174
+ const withdrawals = this.filterBy(response, 'type', 'WITHDRAWAL');
2175
+ const deposits = this.filterBy(response, 'type', 'DEPOSIT');
2176
+ const rows = this.arrayConcat(withdrawals, deposits);
2177
+ return this.parseTransactions(rows, currency, since, limit);
2178
+ }
2179
+ async fetchTransactionsHelper(code = undefined, since = undefined, limit = undefined, params = {}) {
2180
+ const methodName = this.safeString(params, 'methodName');
2181
+ params = this.omit(params, 'methodName');
2182
+ let userAddress = undefined;
2183
+ let subAccountNumber = undefined;
2184
+ [userAddress, params] = this.handlePublicAddress(methodName, params);
2185
+ [subAccountNumber, params] = this.handleOptionAndParams(params, methodName, 'subAccountNumber', '0');
2186
+ const request = {
2187
+ 'address': userAddress,
2188
+ 'subaccountNumber': subAccountNumber,
2189
+ };
2190
+ const response = await this.indexerGetTransfers(this.extend(request, params));
2191
+ //
2192
+ // {
2193
+ // "transfers": [
2194
+ // {
2195
+ // "id": "6a6075bc-7183-5fd9-bc9d-894e238aa527",
2196
+ // "sender": {
2197
+ // "address": "dydx14zzueazeh0hj67cghhf9jypslcf9sh2n5k6art",
2198
+ // "subaccountNumber": 0
2199
+ // },
2200
+ // "recipient": {
2201
+ // "address": "dydx1slanxj8x9ntk9knwa6cvfv2tzlsq5gk3dshml0",
2202
+ // "subaccountNumber": 1
2203
+ // },
2204
+ // "size": "0.000001",
2205
+ // "createdAt": "2025-07-29T09:43:02.105Z",
2206
+ // "createdAtHeight": "45116125",
2207
+ // "symbol": "USDC",
2208
+ // "type": "TRANSFER_OUT",
2209
+ // "transactionHash": "92B4744BA1B783CF37C79A50BEBC47FFD59C8D5197D62A8485D3DCCE9AF220AF"
2210
+ // }
2211
+ // ]
2212
+ // }
2213
+ //
2214
+ return this.safeList(response, 'transfers', []);
2215
+ }
2216
+ /**
2217
+ * @method
2218
+ * @name dydx#fetchAccounts
2219
+ * @description fetch all the accounts associated with a profile
2220
+ * @see https://docs.dydx.xyz/indexer-client/http#get-subaccounts
2221
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2222
+ * @param {string} [params.address] wallet address that made trades
2223
+ * @returns {object} a dictionary of [account structures]{@link https://docs.ccxt.com/#/?id=account-structure} indexed by the account type
2224
+ */
2225
+ async fetchAccounts(params = {}) {
2226
+ let userAddress = undefined;
2227
+ [userAddress, params] = this.handlePublicAddress('fetchAccounts', params);
2228
+ const request = {
2229
+ 'address': userAddress,
2230
+ };
2231
+ const response = await this.indexerGetAddressesAddress(this.extend(request, params));
2232
+ //
2233
+ // {
2234
+ // "subaccounts": [
2235
+ // {
2236
+ // "address": "dydx14zzueazeh0hj67cghhf9jypslcf9sh2n5k6art",
2237
+ // "subaccountNumber": 0,
2238
+ // "equity": "25346.73993597",
2239
+ // "freeCollateral": "24207.8530595294",
2240
+ // "openPerpetualPositions": {
2241
+ // "BTC-USD": {
2242
+ // "market": "BTC-USD",
2243
+ // "status": "OPEN",
2244
+ // "side": "SHORT",
2245
+ // "size": "-0.491",
2246
+ // "maxSize": "-0.009",
2247
+ // "entryPrice": "118703.60811320754716981132",
2248
+ // "exitPrice": "119655.95",
2249
+ // "realizedPnl": "3075.17994830188679245283016",
2250
+ // "unrealizedPnl": "1339.12776155490566037735812",
2251
+ // "createdAt": "2025-07-14T07:53:55.631Z",
2252
+ // "createdAtHeight": "44140908",
2253
+ // "closedAt": null,
2254
+ // "sumOpen": "0.53",
2255
+ // "sumClose": "0.038",
2256
+ // "netFunding": "3111.36894",
2257
+ // "subaccountNumber": 0
2258
+ // }
2259
+ // },
2260
+ // "assetPositions": {
2261
+ // "USDC": {
2262
+ // "size": "82291.083758",
2263
+ // "symbol": "USDC",
2264
+ // "side": "LONG",
2265
+ // "assetId": "0",
2266
+ // "subaccountNumber": 0
2267
+ // }
2268
+ // },
2269
+ // "marginEnabled": true,
2270
+ // "updatedAtHeight": "45234659",
2271
+ // "latestProcessedBlockHeight": "45293477"
2272
+ // }
2273
+ // ]
2274
+ // }
2275
+ //
2276
+ const rows = this.safeList(response, 'subaccounts', []);
2277
+ const result = [];
2278
+ for (let i = 0; i < rows.length; i++) {
2279
+ const account = rows[i];
2280
+ const accountId = this.safeString(account, 'subaccountNumber');
2281
+ result.push({
2282
+ 'id': accountId,
2283
+ 'type': undefined,
2284
+ 'currency': undefined,
2285
+ 'info': account,
2286
+ 'code': undefined,
2287
+ });
2288
+ }
2289
+ return result;
2290
+ }
2291
+ /**
2292
+ * @method
2293
+ * @name dydx#fetchBalance
2294
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
2295
+ * @see https://docs.dydx.xyz/indexer-client/http#get-subaccount
2296
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
2297
+ * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
2298
+ */
2299
+ async fetchBalance(params = {}) {
2300
+ await this.loadMarkets();
2301
+ let userAddress = undefined;
2302
+ [userAddress, params] = this.handlePublicAddress('fetchAccounts', params);
2303
+ let subaccountNumber = undefined;
2304
+ [subaccountNumber, params] = this.handleOptionAndParams(params, 'fetchAccounts', 'subaccountNumber', 0);
2305
+ const request = {
2306
+ 'address': userAddress,
2307
+ 'subaccountNumber': subaccountNumber,
2308
+ };
2309
+ const response = await this.indexerGetAddressesAddressSubaccountNumberSubaccountNumber(this.extend(request, params));
2310
+ //
2311
+ // {
2312
+ // "subaccount": {
2313
+ // "address": "dydx14zzueazeh0hj67cghhf9jypslcf9sh2n5k6art",
2314
+ // "subaccountNumber": 0,
2315
+ // "equity": "161451.040416029",
2316
+ // "freeCollateral": "152508.28819133578",
2317
+ // "openPerpetualPositions": {
2318
+ // "ETH-USD": {
2319
+ // "market": "ETH-USD",
2320
+ // "status": "OPEN",
2321
+ // "side": "LONG",
2322
+ // "size": "0.001",
2323
+ // "maxSize": "0.002",
2324
+ // "entryPrice": "3894.7",
2325
+ // "exitPrice": "3864.5",
2326
+ // "realizedPnl": "-0.034847",
2327
+ // "unrealizedPnl": "-0.044675155",
2328
+ // "createdAt": "2025-10-22T08:34:05.883Z",
2329
+ // "createdAtHeight": "52228825",
2330
+ // "closedAt": null,
2331
+ // "sumOpen": "0.002",
2332
+ // "sumClose": "0.001",
2333
+ // "netFunding": "-0.004647",
2334
+ // "subaccountNumber": 0
2335
+ // },
2336
+ // "BTC-USD": {
2337
+ // "market": "BTC-USD",
2338
+ // "status": "OPEN",
2339
+ // "side": "SHORT",
2340
+ // "size": "-4.1368",
2341
+ // "maxSize": "-0.009",
2342
+ // "entryPrice": "112196.87848803433219017636",
2343
+ // "exitPrice": "113885.21872652924977050823",
2344
+ // "realizedPnl": "-15180.426770788459736511679821",
2345
+ // "unrealizedPnl": "17002.285719484425404321566048",
2346
+ // "createdAt": "2025-07-14T07:53:55.631Z",
2347
+ // "createdAtHeight": "44140908",
2348
+ // "closedAt": null,
2349
+ // "sumOpen": "5.3361",
2350
+ // "sumClose": "1.1983",
2351
+ // "netFunding": "-13157.288663",
2352
+ // "subaccountNumber": 0
2353
+ // }
2354
+ // },
2355
+ // "assetPositions": {
2356
+ // "USDC": {
2357
+ // "size": "608580.951601",
2358
+ // "symbol": "USDC",
2359
+ // "side": "LONG",
2360
+ // "assetId": "0",
2361
+ // "subaccountNumber": 0
2362
+ // }
2363
+ // },
2364
+ // "marginEnabled": true,
2365
+ // "updatedAtHeight": "52228833",
2366
+ // "latestProcessedBlockHeight": "52246761"
2367
+ // }
2368
+ // }
2369
+ //
2370
+ const data = this.safeDict(response, 'subaccount');
2371
+ return this.parseBalance(data);
2372
+ }
2373
+ parseBalance(response) {
2374
+ const account = this.account();
2375
+ account['free'] = this.safeString(response, 'freeCollateral');
2376
+ const result = {
2377
+ 'info': response,
2378
+ 'USDC': account,
2379
+ };
2380
+ return this.safeBalance(result);
2381
+ }
2382
+ nonce() {
2383
+ return this.milliseconds() - this.options['timeDifference'];
2384
+ }
2385
+ getWalletAddress() {
2386
+ if (this.walletAddress !== undefined && this.walletAddress !== '') {
2387
+ return this.walletAddress;
2388
+ }
2389
+ const dydxAccount = this.safeDict(this.options, 'dydxAccount');
2390
+ if (dydxAccount !== undefined) {
2391
+ // return dydxAccount;
2392
+ const wallet = this.safeString(dydxAccount, 'address');
2393
+ if (wallet !== undefined) {
2394
+ return wallet;
2395
+ }
2396
+ }
2397
+ throw new errors.ArgumentsRequired(this.id + ' getWalletAddress() requires a wallet address. Set `walletAddress` or `dydxAccount` in exchange options.');
2398
+ }
2399
+ sign(path, section = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
2400
+ const pathWithParams = this.implodeParams(path, params);
2401
+ let url = this.implodeHostname(this.urls['api'][section]);
2402
+ params = this.omit(params, this.extractParams(path));
2403
+ params = this.keysort(params);
2404
+ url += '/' + pathWithParams;
2405
+ if (method === 'GET') {
2406
+ if (Object.keys(params).length) {
2407
+ url += '?' + this.urlencode(params);
2408
+ }
2409
+ }
2410
+ else {
2411
+ body = this.json(params);
2412
+ headers = {
2413
+ 'Content-type': 'application/json',
2414
+ };
2415
+ }
2416
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
2417
+ }
2418
+ handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
2419
+ if (!response) {
2420
+ return undefined; // fallback to default error handler
2421
+ }
2422
+ //
2423
+ // abci response
2424
+ // { "result": { "code": 0 } }
2425
+ //
2426
+ // rest response
2427
+ // { "code": 123 }
2428
+ //
2429
+ const result = this.safeDict(response, 'result');
2430
+ let errorCode = this.safeString(result, 'code');
2431
+ if (!errorCode) {
2432
+ errorCode = this.safeString(response, 'code');
2433
+ }
2434
+ if (errorCode) {
2435
+ const errorCodeNum = this.parseToNumeric(errorCode);
2436
+ if (errorCodeNum > 0) {
2437
+ const feedback = this.id + ' ' + this.json(response);
2438
+ this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
2439
+ this.throwBroadlyMatchedException(this.exceptions['broad'], body, feedback);
2440
+ throw new errors.ExchangeError(feedback);
2441
+ }
2442
+ }
2443
+ return undefined;
2444
+ }
2445
+ setSandboxMode(enable) {
2446
+ super.setSandboxMode(enable);
2447
+ // rewrite testnet parameters
2448
+ this.options['chainName'] = 'dydx-testnet-4';
2449
+ this.options['chainId'] = 11155111;
2450
+ this.options['feeDenom']['CHAINTOKEN_DENOM'] = 'adv4tnt';
2451
+ }
2452
+ }
2453
+
2454
+ exports["default"] = dydx;