В процессе загрузки ресурсов... загрузка...

Количественная практика обмена DEX (1) -- руководство пользователя dYdX v4

Автор:FMZ~Lydia, Создано: 2024-12-26 15:32:24, Обновлено: 2024-12-26 17:36:31

Преамбула

С быстрым ростом децентрализованных бирж (DEX) в области торговли криптовалютами количественные трейдеры постепенно обращаются к этим платформам для эффективной автоматизированной торговли.

В этой статье будет представлено, как практиковать количественную торговлю на dYdX v4, в том числе как использовать его API для торговли, получения рыночных данных и управления счетами.

  • Смена среды испытания
  • Запрос информации о рынке
  • Запрос информации о заказе и информации о позиции
  • Заказать
  • Управление субсчетами
  • Запрос на метод узла

dYdX v4 DEX

  • dYdX testnet Приложение страницы

img

  • КакdYdX v3с Ethereum, торговля генерирует вознаграждения, которые являются вознаграждениемdYdX tokens.

Подключение кошелька, логин и конфигурация

Предыдущий обмен DEX протокола dYdX v3 был отключен.

https://dydx.trade/trade/ETH-USD

После открытия страницы приложения в правом верхнем углу расположена кнопка для подключения к кошельку.

Если вы хотите сначала протестировать и ознакомиться с средой тестовой сети, вы можете использовать тестовую сеть:

https://v4.testnet.dydx.exchange/trade/ETH-USD

Кроме того, нажмите кнопку подключения кошелька в правом верхнем углу, сканируйте код для подключения кошелька и проверьте подпись. После успешного подключения кошелька автоматически будет сгенерирован адрес dydx v4. Этот адрес будет отображаться в правом верхнем углу страницы приложения. Нажмите на него, и всплывет меню. Есть такие операции, как подзарядка, снятие и передача. Одно из отличий между основным сетью dYdX (производственная среда) и тестовой сетью заключается в том, что при нажатии на кнопку подзарядки на тестовой сети 300 USDC активов будут автоматически заряжены с помощью крана для тестирования. Если вы хотите совершать реальные транзакции на dYdX, вам нужно заряжать активы в USDC. Подзарядка также очень удобна и совместима с несколькими активами и цепями для подзарядки.

  • Адрес учетной записи dYdX v4 Адрес учетной записи dYdX v4 получен из адреса кошелька.dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx, который является адресом, начинающимся с dydx1. Этот адрес можно запросить в блокчейн-эксплорерах.

  • Мнемоника Вы можете использовать кнопку Export Password в меню в правом верхнем углу, чтобы экспортировать мнемонику текущего аккаунта адреса dYdX. При добавлении обмена на платформе FMZ вам нужно настроить эту мнемонику.

При использовании объекта обмена dydx v4 будет прочитано содержание файла, записывающего мнемонику, что будет продемонстрировано в практической части этой статьи.

Различия между Mainnet и Testnet

Окружающая среда тестовой сети в некоторых аспектах отличается от среды основной сети.

  • Перевод активов на субсчет. В основной сети есть механизм очистки подсчетов.subAccountNumber >= 128, если на подсчете ID нет позиций, активы автоматически очищаются на подсчет, номер подсчета которого равен 0. Во время испытаний было установлено, что испытательная сеть не имеет этого механизма (или условия запуска отличаются, и она не была задействована в испытательной сети).
  • Некоторые символические имена. Нативный токен dydx имеет разные названия: mainnetDYDX, испытательная сетьDv4TNT
  • Конфигурация адреса, например, идентификатор цепи, адрес узла, адрес индексатора и т.д. Есть много узлов и конфигураций, вот один из них:

Главная сеть: Адрес индексатора:https://indexer.dydx.tradeИдентификатор цепи:dydx-mainnet-1РЕСТ-узел:https://dydx-dao-api.polkachu.com:443

Пробная сеть: Адрес индексатора:https://indexer.v4testnet.dydx.exchangeИдентификатор цепи:dydx-testnet-4РЕСТ-узел:https://dydx-testnet-api.polkachu.com

Архитектура протокола dYdX v4

Протокол dYdX v4 разработан на основе экосистемы космоса.

  • Индексер, отвечающий за запрос информации о тикере, информации о счете и т.д.
  • dydx блокчейн сообщения о заказах, сообщения об отмене заказов, сообщения о переводе и т.д.

Индексер

Услуга индексатора предоставляет протоколы REST и Websocket.

  • Протокол REST Интерфейс протокола REST поддерживает запрос на информацию о рынке, информацию о счете, информацию о позиции, информацию о заказах и другие запросы, и был инкапсулирован как единый интерфейс API на платформе FMZ.

  • Протокол WebSocket На платформе FMZ вы можете использовать функцию Dial для создания соединения Websocket и подписки на информацию о рынке.

Следует отметить, что индексер dydx v4 имеет ту же проблему, что и централизованные биржи, то есть обновления данных не так своевременны.Sleep(n)) определенные операции перед запросом.

Вот пример использования функции Dial для создания API-соединения Websocket и подписки на данные книги заказов:

function dYdXIndexerWSconnManager(streamingPoint) {
    var self = {}
    self.base = streamingPoint
    self.wsThread = null

    // subscription
    self.CreateWsThread = function (msgSubscribe) {
        self.wsThread = threading.Thread(function (streamingPoint, msgSubscribe) {
            // Order book
            var orderBook = null 

            // Update order book
            var updateOrderbook = function(orderbook, update) {
                // Update bids
                if (update.bids) {
                    update.bids.forEach(([price, size]) => {
                        const priceFloat = parseFloat(price)
                        const sizeFloat = parseFloat(size)

                        if (sizeFloat === 0) {
                            // Delete the buy order with price
                            orderbook.bids = orderbook.bids.filter(bid => parseFloat(bid.price) !== priceFloat)
                        } else {
                            // Update or add a buy order
                            orderbook.bids = orderbook.bids.filter(bid => parseFloat(bid.price) !== priceFloat)
                            orderbook.bids.push({price: price, size: size})
                            // Sort by price descending
                            orderbook.bids.sort((a, b) => parseFloat(b.price) - parseFloat(a.price))
                        }
                    })
                }

                // Update asks
                if (update.asks) {
                    update.asks.forEach(([price, size]) => {
                        const priceFloat = parseFloat(price)
                        const sizeFloat = parseFloat(size)

                        if (sizeFloat === 0) {
                            // Delete the sell order with price
                            orderbook.asks = orderbook.asks.filter(ask => parseFloat(ask.price) !== priceFloat)
                        } else {
                            // Update or add a sell order
                            orderbook.asks = orderbook.asks.filter(ask => parseFloat(ask.price) !== priceFloat)
                            orderbook.asks.push({price: price, size: size})
                            // Sort by price ascending
                            orderbook.asks.sort((a, b) => parseFloat(a.price) - parseFloat(b.price))
                        }
                    })
                }

                return orderbook
            }

            var conn = Dial(`${streamingPoint}|reconnect=true&payload=${JSON.stringify(msgSubscribe)}`)
            if (!conn) {
                Log("createWsThread failed.")
                return
            }
            while (true) {
                var data = conn.read()
                if (data) {
                    var msg = null                    
                    try {
                        msg = JSON.parse(data)
                        if (msg["type"] == "subscribed") {
                            orderBook = msg["contents"]
                            threading.currentThread().postMessage(orderBook)
                        } else if (msg["type"] == "channel_data") {
                            orderBook = updateOrderbook(orderBook, msg["contents"])
                            threading.currentThread().postMessage(orderBook)
                        }
                    } catch (e) {
                        Log("e.name:", e.name, "e.stack:", e.stack, "e.message:", e.message)
                    }
                }
            }
        }, streamingPoint, msgSubscribe)
    }

    // monitor
    self.Peek = function () {
        return self.wsThread.peekMessage()
    }

    return self
}

function main() {
    // real : wss://indexer.dydx.trade/v4/ws
    // simulate : wss://indexer.v4testnet.dydx.exchange/v4/ws

    var symbol = "ETH-USD"
    var manager = dYdXIndexerWSconnManager("wss://indexer.dydx.trade/v4/ws")
    manager.CreateWsThread({"type": "subscribe", "channel": "v4_orderbook", "id": symbol})

    var redCode = "#FF0000"
    var greenCode = "#006400"
    while (true) {
        var depthTbl = {type: "table", title: symbol + " / depth", cols: ["level", "price", "amount"], rows: []}
        var depth = manager.Peek()
        if (depth) {
            for (var i = 0; i < depth.asks.length; i++) {
                if (i > 9) {
                    break
                }
                var ask = depth.asks[i]
                depthTbl.rows.push(["asks " + (i + 1) + greenCode, ask.price + greenCode, ask.size + greenCode])
            }
            depthTbl.rows.reverse()

            for (var i = 0; i < depth.bids.length; i++) {
                if (i > 9) {
                    break
                }
                var bid = depth.bids[i]
                depthTbl.rows.push(["bids " + (i + 1) + redCode, bid.price + redCode, bid.size + redCode])
            }
        }
        LogStatus(_D(), "\n`" + JSON.stringify(depthTbl) + "`")
    }
}

Распространение сообщения dYdX Chain Node

Наиболее часто используемые сообщения в транзакциях - это сообщения о заказе, сообщения об отмене заказа и сообщения о переводе.

  • Резюме сообщения о заказе
{
  "@type": "/dydxprotocol.clob.MsgPlaceOrder",
  "order": {
    "orderId": {
      "subaccountId": {
        "owner": "xxx"
      },
      "clientId": xxx,
      "orderFlags": 64,
      "clobPairId": 1
    },
    "side": "SIDE_BUY",
    "quantums": "2000000",
    "subticks": "3500000000",
    "goodTilBlockTime": 1742295981
  }
}
  • Лимитный порядок: В функции ордеров, встроенной на платформе FMZ, значение orderFlags, используемое для предельных ордеров, составляет:ORDER_FLAGS_LONG_TERM = 64 # Long-term orderСогласно ограничениям протокола dydx v4, используется самый длинный срок действия заказа, который составляет 90 дней (все типы заказов на dydx v4 имеют периоды действия).

  • Рыночный порядок: В функции заказов, включенной в платформу FMZ, значение orderFlags, используемое для рыночных заказов, составляет:ORDER_FLAGS_SHORT_TERM = 0 # Short-term order, согласно рекомендациям протокола dydx v4:

// Рекомендую установить цену Oracle - 5% или ниже для SELL, цену Oracle + 5% для BUY

Поскольку это не настоящий рыночный ордер, используется цена оракула, плюс или минус 5% скольжение как рыночный ордер. Период действия краткосрочных ордеров также отличается от долгосрочных ордеров.

  • Идентификатор заказа: Поскольку операция заказа выполняется непосредственно на цепочке, после трансляции сообщения индексером не будет генерироваться идентификатор заказа, и индексовый порядок не может использоваться в качестве возвращаемого значения функции заказа платформы.

Торговые пары адрес текущего счета dydx Номер субсчета (субсчета) ClientId (случайный) clobPairId (идентификатор символа транзакции) порядокФлаги goodTilData (миллисекунды)

  • Резюме сообщения об отмене заказа
{
  "@type": "/dydxprotocol.clob.MsgCancelOrder",
  "orderId": {
    "subaccountId": {
      "owner": "xxx"
    },
    "clientId": 2585872024,
    "orderFlags": 64,
    "clobPairId": 1
  },
  "goodTilBlockTime": 1742295981
}

Идентификатор заказа, возвращаемый интерфейсом заказа платформы FMZ, должен быть передан.

  • Резюме сообщения о передаче
{
  "@type": "/dydxprotocol.sending.MsgCreateTransfer",
  "transfer": {
    "sender": {
      "owner": "xxx"
    },
    "recipient": {
      "owner": "xxx",
      "number": 128
    },
    "amount": "10000000"
  }
}

Многие подсчеты могут быть созданы под текущим адресом dydx v4. Подсчет с подсчетомNo0 является первым автоматически созданным подсчетом. ID подсчета с подсчетомNo128 больше или равно 128 используется для торговли изолированной позицией, которая требует не менее 20 активов USDC. Например, вы можете перейти от подсчета No0 -> 128 или от подсчета No128 -> 0. Переводы требуют оплаты за газ. За газ можно платить USDC или токены dydx.

Платформа FMZ dYdX v4 Практика

Вышеприведенный контент кратко объясняет некоторые детали упаковки. Далее, давайте практикуем конкретное использование. Здесь мы используем тестовую сеть dYdX v4 для демонстрации. Тестовая сеть в основном такая же, как и основная сеть, и есть автоматический кран для приема тестовых активов. Операция развертывания докера не будет повторяться. Создайте живое торговое испытание на FMZ.

1. Конфигурация

После успешного подключения к приложению dYdX v4 с помощью криптовалютного кошелька (я использую кошелек imToken здесь), воспользуйтесь своими тестовыми активами, а затем экспортируйте мнемонику для текущей учетной записи dYdX v4 (выведенной из вашего кошелька).

img

Конфигурировать мнемонику на платформе FMZ. Здесь мы используем метод локального файла для его конфигурации (вы также можете заполнить его напрямую и настроить его на платформе. Мнемоника настроена после шифрования, а не в простом тексте).

  • Файл mnemonic: mnemonic.txt

img

Разумеется, он также может быть размещен в других каталогах (конкретный путь должен быть написан во время настройки).

  • Настроить обмен на FMZ

https://www.fmz.com/m/platforms/add

Заполните рамку редактирования:file:///mnemonic.txt, соответствующий фактический путь:docker directory/logs/storage/594291.

img

2. Перейти на dydx v4 тестовую сеть

function main() {
    // Switch the indexer address of the test chain
    exchange.SetBase("https://indexer.v4testnet.dydx.exchange")

    // Switch the ChainId of the test chain
    exchange.IO("chainId", "dydx-testnet-4")

    // Switch the REST node address of the test chain
    exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")

    // Read account information test
    Log(exchange.GetAccount()) 
}

Прочитайте информацию о учетной записи сети тестирования:

{
	"Info": {
		"subaccounts": [{
			"address": "dydx1fzsndj35a26maujxff88q2ge5jr4nzfeljn2ez",
			"subaccountNumber": 0,
			"equity": "300.386228",
			"latestProcessedBlockHeight": "28193227",
			"freeCollateral": "300.386228",
			"openPerpetualPositions": {},
			"assetPositions": {
				"USDC": {
					"subaccountNumber": 0,
					"size": "300.386228",
					"symbol": "USDC",
					"side": "LONG",
					"assetId": "0"
				}
			},
			"marginEnabled": true,
			"updatedAtHeight": "28063818"
		}, {
			"address": "dydx1fzsndj35a26maujxff88q2ge5jr4nzfeljn2ez",
			"equity": "0",
			"freeCollateral": "0",
			"openPerpetualPositions": {},
			"marginEnabled": true,
			"subaccountNumber": 1,
			"assetPositions": {},
			"updatedAtHeight": "27770289",
			"latestProcessedBlockHeight": "28193227"
		}, {
			"equity": "0",
			"openPerpetualPositions": {},
			"marginEnabled": true,
			"updatedAtHeight": "28063818",
			"latestProcessedBlockHeight": "28193227",
			"subaccountNumber": 128,
			"freeCollateral": "0",
			"assetPositions": {},
			"address": "dydx1fzsndj35a26maujxff88q2ge5jr4nzfeljn2ez"
		}],
		"totalTradingRewards": "0.021744179376211564"
	},
	"Stocks": 0,
	"FrozenStocks": 0,
	"Balance": 300.386228,
	"FrozenBalance": 0,
	"Equity": 300.386228,
	"UPnL": 0
}

3.Исследование информации о рынке

Не переключился на тестовую сеть, испытанную с основной сетью

function main() {
    var markets = exchange.GetMarkets()
    if (!markets) {
        throw "get markets error"
    }
    var tbl = {type: "table", title: "test markets", cols: ["key", "Symbol", "BaseAsset", "QuoteAsset", "TickSize", "AmountSize", "PricePrecision", "AmountPrecision", "MinQty", "MaxQty", "MinNotional", "MaxNotional", "CtVal"], rows: []}
    for (var symbol in markets) {
        var market = markets[symbol]
        tbl.rows.push([symbol, market.Symbol, market.BaseAsset, market.QuoteAsset, market.TickSize, market.AmountSize, market.PricePrecision, market.AmountPrecision, market.MinQty, market.MaxQty, market.MinNotional, market.MaxNotional, market.CtVal])
    }
    LogStatus("`" + JSON.stringify(tbl) +  "`")
}

img

4. Заказать

function main() {
    // Switch the indexer address of the test chain
    exchange.SetBase("https://indexer.v4testnet.dydx.exchange")

    // Switch the ChainId of the test chain
    exchange.IO("chainId", "dydx-testnet-4")

    // Switch the REST node address of the test chain
    exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")

    // Limit order, pending order
    var idSell = exchange.CreateOrder("ETH_USD.swap", "sell", 4000, 0.002)
    var idBuy = exchange.CreateOrder("ETH_USD.swap", "buy", 3000, 0.003)

    // Market order
    var idMarket = exchange.CreateOrder("ETH_USD.swap", "buy", -1, 0.01)

    Log("idSell:", idSell)
    Log("idBuy:", idBuy)
    Log("idMarket:", idMarket)
}

img

Страница приложения dYdX v4:

img

5. Информация о заказе

Испытательная сеть размещает два заказа заранее, тестирует получение текущих ожидаемых заказов и отменяет заказы.

function main() {    
    // Switch the indexer address of the test chain
    exchange.SetBase("https://indexer.v4testnet.dydx.exchange")

    // Switch the ChainId of the test chain
    exchange.IO("chainId", "dydx-testnet-4")

    // Switch the REST node address of the test chain
    exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")

    var orders = exchange.GetOrders()
    Log("orders:", orders)
    for (var order of orders) {
        exchange.CancelOrder(order.Id, order)
        Sleep(2000)
    }

    var tbl = {type: "table", title: "test GetOrders", cols: ["Id", "Price", "Amount", "DealAmount", "AvgPrice", "Status", "Type", "Offset", "ContractType"], rows: []}
    for (var order of orders) {
        tbl.rows.push([order.Id, order.Price, order.Amount, order.DealAmount, order.AvgPrice, order.Status, order.Type, order.Offset, order.ContractType])
    }
    LogStatus("`" + JSON.stringify(tbl) +  "`")
}

img

6. Запрос информации о должности

function main() {
    // Switch the indexer address of the test chain
    exchange.SetBase("https://indexer.v4testnet.dydx.exchange")

    // Switch the ChainId of the test chain
    exchange.IO("chainId", "dydx-testnet-4")

    // Switch the REST node address of the test chain
    exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")

    var p1 = exchange.GetPositions("USD.swap")
    var p2 = exchange.GetPositions("ETH_USD.swap")
    var p3 = exchange.GetPositions()
    var p4 = exchange.GetPositions("SOL_USD.swap")

    var tbls = []
    for (var positions of [p1, p2, p3, p4]) {
        var tbl = {type: "table", title: "test GetPosition/GetPositions", cols: ["Symbol", "Amount", "Price", "FrozenAmount", "Type", "Profit", "Margin", "ContractType", "MarginLevel"], rows: []}
        for (var p of positions) {
            tbl.rows.push([p.Symbol, p.Amount, p.Price, p.FrozenAmount, p.Type, p.Profit, p.Margin, p.ContractType, p.MarginLevel])
        } 
        tbls.push(tbl)
    }

    LogStatus("`" + JSON.stringify(tbls) +  "`")
}

img

7. Управление подсчетами

function main() {
    // Switch the indexer address of the test chain
    exchange.SetBase("https://indexer.v4testnet.dydx.exchange")

    // Switch the ChainId of the test chain
    exchange.IO("chainId", "dydx-testnet-4")

    // Switch the REST node address of the test chain
    exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")

    // subAccountNumber 0 -> 128 : 20 USDC, Gas Fee is adv4tnt, i.e. dydx token
    // var ret = exchange.IO("transferUSDCToSubaccount", 0, 128, "adv4tnt", 20)  
    // Log("ret:", ret)

    // Switch to subaccount subAccountNumber 128 and read account information to check
    exchange.IO("subAccountNumber", 128)

    var account = exchange.GetAccount()
    Log("account:", account)
}

Информация о журнале:

img

Переключитесь на подсчет, чьё подсчетное число 128, и данные, возвращенные GetAccount:

{
	"Info": {
		"subaccounts": [{
			"subaccountNumber": 0,
			"assetPositions": {
				"USDC": {
					"size": "245.696892",
					"symbol": "USDC",
					"side": "LONG",
					"assetId": "0",
					"subaccountNumber": 0
				}
			},
			"updatedAtHeight": "28194977",
			"latestProcessedBlockHeight": "28195008",
			"address": "dydx1fzsndj35a26maujxff88q2ge5jr4nzfeljn2ez",
			"freeCollateral": "279.5022142346",
			"openPerpetualPositions": {
				"ETH-USD": {
					"closedAt": null,
					"size": "0.01",
					"maxSize": "0.01",
					"exitPrice": null,
					"unrealizedPnl": "-0.17677323",
					"subaccountNumber": 0,
					"status": "OPEN",
					"createdAt": "2024-12-26T03:36:09.264Z",
					"createdAtHeight": "28194494",
					"sumClose": "0",
					"netFunding": "0",
					"market": "ETH-USD",
					"side": "LONG",
					"entryPrice": "3467.2",
					"realizedPnl": "0",
					"sumOpen": "0.01"
				}
			},
			"marginEnabled": true,
			"equity": "280.19211877"
		}, {
			"openPerpetualPositions": {},
			"assetPositions": {},
			"marginEnabled": true,
			"latestProcessedBlockHeight": "28195008",
			"address": "dydx1fzsndj35a26maujxff88q2ge5jr4nzfeljn2ez",
			"subaccountNumber": 1,
			"equity": "0",
			"freeCollateral": "0",
			"updatedAtHeight": "27770289"
		}, {
			"openPerpetualPositions": {},
			"updatedAtHeight": "28194977",
			"latestProcessedBlockHeight": "28195008",
			"address": "dydx1fzsndj35a26maujxff88q2ge5jr4nzfeljn2ez",
			"subaccountNumber": 128,
			"assetPositions": {
				"USDC": {
					"assetId": "0",
					"subaccountNumber": 128,
					"size": "20",
					"symbol": "USDC",
					"side": "LONG"
				}
			},
			"marginEnabled": true,
			"equity": "20",
			"freeCollateral": "20"
		}],
		"totalTradingRewards": "0.021886899964446858"
	},
	"Stocks": 0,
	"FrozenStocks": 0,
	"Balance": 20,
	"FrozenBalance": 0,
	"Equity": 20,
	"UPnL": 0
}

Видно, что на подсчете с подсчетом No 128 было перечислено 20 долларов США.

8. Получить TxHash и вызвать интерфейс REST Node

Согласно приказу, получить TxHash и проверить метод IO вызвать REST узла

Как получить TxHash заказа? Объект обмена dydx будет кэшировать TxHash, который можно запросить с помощью идентификатора заказа. Однако после того, как стратегия будет остановлена, кэшированная карта хэша заказа tx будет удалена.

function main() {
    // Switch the indexer address of the test chain
    exchange.SetBase("https://indexer.v4testnet.dydx.exchange")

    // Switch the ChainId of the test chain
    exchange.IO("chainId", "dydx-testnet-4")

    // Switch the REST node address of the test chain
    exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")

    var id1 = exchange.CreateOrder("ETH_USD.swap", "buy", 3000, 0.002)
    var hash1 = exchange.IO("getTxHash", id1)
    Log("id1:", id1, "hash1:", hash1)

    var id2 = exchange.CreateOrder("ETH_USD.swap", "buy", 2900, 0.003)
    var hash2 = exchange.IO("getTxHash", id2)
    Log("id2:", id2, "hash2:", hash2)
    
    // To clear the mapping table, use: exchange.IO("getTxHash", "")
    var arr = [hash1, hash2]
    
    Sleep(10000)
    for (var txHash of arr) {
        // GET https://docs.cosmos.network   /cosmos/tx/v1beta1/txs/{hash}
        var ret = exchange.IO("api", "GET", "/cosmos/tx/v1beta1/txs/" + txHash)
        Log("ret:", ret)
    }
}

img

Сообщения, запрошенные через TxHash:

var ret =exchange.IO("api", GET, /cosmos/tx/v1beta1/txs/ + txHash)

Содержание слишком длинное, поэтому вот некоторые выдержки для демонстрации:

{
	"tx_response": {
		"codespace": "",
		"code": 0,
		"logs": [],
		"info": "",
		"height": "28195603",
		"data": "xxx",
		"raw_log": "",
		"gas_wanted": "-1",
		"gas_used": "0",
		"tx": {
			"@type": "/cosmos.tx.v1beta1.Tx",
			"body": {
				"messages": [{
					"@type": "/dydxprotocol.clob.MsgPlaceOrder",
					"order": {
						"good_til_block_time": 1742961542,
						"condition_type": "CONDITION_TYPE_UNSPECIFIED",
						"order_id": {
							"clob_pair_id": 1,
							"subaccount_id": {
								"owner": "xxx",
								"number": 0
							},
							"client_id": 2999181974,
							"order_flags": 64
						},
						"side": "SIDE_BUY",
						"quantums": "3000000",
						"client_metadata": 0,
						"conditional_order_trigger_subticks": "0",
						"subticks": "2900000000",
						"time_in_force": "TIME_IN_FORCE_UNSPECIFIED",
						"reduce_only": false
					}
				}],
				"memo": "FMZ",
				"timeout_height": "0",
				"extension_options": [],
				"non_critical_extension_options": []
			},
      ...

Конец

Вышеприведенные тесты основаны на новейшей версии докера. Вам нужно скачать новейшую версию докера для поддержки dYdX v4 DEX

Спасибо за поддержку и за чтение.


Больше