[TOC]

Avec l’essor rapide des échanges décentralisés (DEX) dans le domaine du trading de crypto-monnaie, les traders quantitatifs ont progressivement commencé à se tourner vers ces plateformes pour un trading automatisé efficace. En tant que l’une des plateformes de trading décentralisées les plus populaires, dYdX offre de puissantes fonctions de trading et prend en charge le trading de contrats à terme perpétuels. Sa dernière version v4 optimise les performances et l’expérience utilisateur, ce qui en fait le premier choix de nombreux traders quantitatifs.
Cet article présentera comment pratiquer le trading quantitatif sur dYdX v4, notamment comment utiliser son API pour trader, obtenir des données de marché et gérer des comptes.

dYdX v3De même, les transactions génèrent des récompenses, des récompensesdYdXJetons.
L’échange DEX du protocole dYdX v3 précédent est hors ligne. L’adresse actuelle de l’application dYdX v4 est :
Après avoir ouvert la page de l’application, un bouton permettant de se connecter au portefeuille se trouve dans le coin supérieur droit. Scannez le code QR pour vous connecter au portefeuille.
Si vous souhaitez d’abord tester et vous familiariser avec l’environnement réseau de test, vous pouvez utiliser le réseau de test :
Cliquez également sur le bouton Connecter le portefeuille dans le coin supérieur droit, scannez le code QR pour vous connecter au portefeuille et vérifiez la signature. Une fois le portefeuille correctement connecté, une adresse dydx v4 sera automatiquement générée. Cette adresse sera affichée dans le coin supérieur droit de la page de l’application. Un menu apparaîtra après avoir cliqué dessus. Il s’agit notamment d’opérations telles que la recharge, le retrait et le transfert. L’une des différences entre le réseau principal dYdX (environnement de production) et le réseau de test est que lorsque vous cliquez sur le bouton de rechargement du réseau de test, 300 actifs USDC seront automatiquement déposés dans le robinet pour les tests. Si vous souhaitez effectuer des transactions réelles sur dYdX, vous devez déposer des actifs USDC. La recharge est également très pratique et compatible avec plusieurs actifs et chaînes.
Adresse du compte dYdX v4
L’adresse du compte dYdX v4 est dérivée de l’adresse du portefeuille. L’adresse du compte dYdX v4 ressemble à ceci :dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx, est l’adresse commençant par dydx1. Cette adresse peut être interrogée dans les explorateurs de blockchain.
Mnémotechnique Vous pouvez exporter le mnémonique du compte d’adresse dYdX actuel en cliquant sur le bouton « Exporter le mot de passe » dans le menu du coin supérieur droit. Lors de l’ajout d’un échange sur la plateforme FMZ, vous devez configurer ce mnémonique.
Les mnémoniques peuvent être configurées directement sur la plateforme FMZ ou enregistrées localement sur le dépositaire. Lors de l’utilisation de l’objet d’échange dydx v4, le contenu du fichier enregistrant les mnémoniques sera lu, ce qui sera démontré dans la partie pratique de cet article.
L’environnement du réseau de test est différent de l’environnement du réseau principal sur certains aspects. Voici quelques différences simples.
Transfert d’actifs de sous-compte.
Le réseau principal dispose d’un mécanisme de nettoyage des sous-comptes.subAccountNumber >= 128Si le sous-compte avec cet ID n’a pas de positions, les actifs seront automatiquement transférés vers le sous-compte avec le subAccountNumber 0.
Lors des tests, il a été constaté que le réseau de test ne disposait pas d’un tel mécanisme (ou que les conditions de déclenchement étaient différentes et qu’il n’avait pas été déclenché sur le réseau de test).
Quelques noms symboliques.
Le jeton natif dydx est nommé différemment : MainnetDYDX, réseau de testDv4TNT
Configuration d’adresse, telle que l’ID de chaîne, l’adresse du nœud, l’adresse de l’indexeur, etc. Il existe de nombreux nœuds et configurations, en voici un :
Réseau principal :
Adresse de l’indexeur :https://indexer.dydx.trade
ID de la chaîne :dydx-mainnet-1
Nœud REST :https://dydx-dao-api.polkachu.com:443
Réseau de test :
Adresse de l’indexeur :https://indexer.v4testnet.dydx.exchange
ID de la chaîne :dydx-testnet-4
Nœud REST :https://dydx-testnet-api.polkachu.com
Le protocole dYdX v4 est développé sur la base de l’écosystème cosmos. Le contenu des transactions du système dYdX v4 DEX se compose principalement de deux parties :
Le service d’indexation fournit les protocoles REST et Websocket.
Protocole REST L’interface du protocole REST prend en charge les requêtes d’informations de marché, les informations de compte, les informations de position, les informations de commande, etc., et a été encapsulée en tant qu’interface API unifiée sur la plate-forme FMZ.
Protocole WebSocket Sur la plateforme FMZ, vous pouvez utiliser la fonction Dial pour créer une connexion Websocket et vous abonner aux informations du marché.
Il convient de noter que l’indexeur dydx v4 présente le même problème que l’échange centralisé, à savoir que les mises à jour des données ne sont pas aussi rapides. Par exemple, il arrive parfois que la commande ne soit pas trouvée lors d’une requête immédiatement après avoir passé une commande. Il est recommandé qu’après certaines opérations (Sleep(n)) Attendez quelques secondes avant de relancer la requête.
Voici un exemple d’utilisation de la fonction Dial pour créer une connexion API Websocket et s’abonner aux données du carnet de commandes :
function dYdXIndexerWSconnManager(streamingPoint) {
var self = {}
self.base = streamingPoint
self.wsThread = null
// 订阅
self.CreateWsThread = function (msgSubscribe) {
self.wsThread = threading.Thread(function (streamingPoint, msgSubscribe) {
// 订单薄
var orderBook = null
// 更新订单薄
var updateOrderbook = function(orderbook, update) {
// 更新 bids
if (update.bids) {
update.bids.forEach(([price, size]) => {
const priceFloat = parseFloat(price)
const sizeFloat = parseFloat(size)
if (sizeFloat === 0) {
// 删除价格为 price 的买单
orderbook.bids = orderbook.bids.filter(bid => parseFloat(bid.price) !== priceFloat)
} else {
// 更新或新增买单
orderbook.bids = orderbook.bids.filter(bid => parseFloat(bid.price) !== priceFloat)
orderbook.bids.push({price: price, size: size})
// 按价格降序排序
orderbook.bids.sort((a, b) => parseFloat(b.price) - parseFloat(a.price))
}
})
}
// 更新 asks
if (update.asks) {
update.asks.forEach(([price, size]) => {
const priceFloat = parseFloat(price)
const sizeFloat = parseFloat(size)
if (sizeFloat === 0) {
// 删除价格为 price 的卖单
orderbook.asks = orderbook.asks.filter(ask => parseFloat(ask.price) !== priceFloat)
} else {
// 更新或新增卖单
orderbook.asks = orderbook.asks.filter(ask => parseFloat(ask.price) !== priceFloat)
orderbook.asks.push({price: price, size: size})
// 按价格升序排序
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)
}
// 监听
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) + "`")
}
}
Les messages les plus couramment utilisés dans les transactions sont les messages de commande, les messages d’annulation de commande et les messages de transfert.
{
"@type": "/dydxprotocol.clob.MsgPlaceOrder",
"order": {
"orderId": {
"subaccountId": {
"owner": "xxx"
},
"clientId": xxx,
"orderFlags": 64,
"clobPairId": 1
},
"side": "SIDE_BUY",
"quantums": "2000000",
"subticks": "3500000000",
"goodTilBlockTime": 1742295981
}
}
Ordre limité :
Dans la fonction de commande encapsulée sur la plateforme FMZ, la valeur orderFlags utilisée pour les ordres à cours limité est :ORDER_FLAGS_LONG_TERM = 64 # 长期订单Conformément aux limitations du protocole DYDX v4, la période de validité de commande la plus longue est utilisée, qui est de 90 jours (tous les types de commandes sur DYDX v4 ont une période de validité).
Ordre du marché :
Dans la fonction de commande encapsulée sur la plateforme FMZ, la valeur orderFlags utilisée par l’ordre au marché est :ORDER_FLAGS_SHORT_TERM = 0 # 短期订单, selon les recommandations du protocole DYDX v4 :
// Recommend set to oracle price - 5% or lower for SELL, oracle price + 5% for BUY
Puisqu’il ne s’agit pas d’un véritable ordre de marché, le prix de l’oracle est utilisé, plus ou moins 5 % de glissement comme ordre de marché. Le réglage de la période de validité des ordres à court terme est également différent de celui des ordres à long terme. Les ordres à court terme utilisent la période de validité de la hauteur de bloc. Selon la recommandation de dydx v4, elle est définie sur le bloc actuel + 10 hauteurs de bloc avant son expiration.
Numéro de commande : Étant donné que l’opération de commande est effectuée directement sur la chaîne, aucun identifiant de commande ne sera généré par l’indexeur après la diffusion du message, et l’ordre de l’indexeur ne peut pas être utilisé comme valeur de retour de la fonction de commande de la plateforme. Afin de garantir l’unicité En fonction de l’ID de commande et de l’exactitude de la requête de commande, l’ordre de l’indexeur est renvoyé. L’ID de commande comprend les informations suivantes (séparées par des virgules) :
Résumé du message d’annulation de commande
{
"@type": "/dydxprotocol.clob.MsgCancelOrder",
"orderId": {
"subaccountId": {
"owner": "xxx"
},
"clientId": 2585872024,
"orderFlags": 64,
"clobPairId": 1
},
"goodTilBlockTime": 1742295981
}
L’ID de commande renvoyé par l’interface de commande de la plateforme FMZ doit être transmis.
{
"@type": "/dydxprotocol.sending.MsgCreateTransfer",
"transfer": {
"sender": {
"owner": "xxx"
},
"recipient": {
"owner": "xxx",
"number": 128
},
"amount": "10000000"
}
}
De nombreux sous-comptes peuvent être créés sous l’adresse dydx v4 actuelle. Le sous-compte avec le subAccountNumber 0 est le premier sous-compte créé automatiquement. L’ID de sous-compte avec le subAccountNumber supérieur ou égal à 128 est utilisé pour le trading de position isolée, qui nécessite au moins 20 USDC d’actifs. Par exemple, vous pouvez passer de subAccountNumber 0 -> 128, ou de subAccountNumber 128 -> 0. Le transfert nécessite la consommation de frais de gaz. Les frais de gaz peuvent utiliser les jetons USDC et dydx.
Le contenu ci-dessus explique brièvement certains détails du packaging. Ensuite, pratiquons l’utilisation spécifique. Ici, nous utilisons le réseau de test dYdX v4 pour la démonstration. Le réseau de test est fondamentalement le même que le réseau principal, et il existe un robinet automatique pour recevoir les ressources de test . Le gardien déploie Je n’entrerai pas dans les détails de l’opération, et créerai un véritable test sur FMZ.
Après vous être connecté avec succès à l’application dYdX v4 à l’aide d’un portefeuille de crypto-monnaie (j’utilise ici le portefeuille imToken), réclamez vos actifs de test, puis exportez le mnémonique de votre compte dYdX v4 actuel (dérivé de votre portefeuille).

Configurer le mnémonique sur la plateforme FMZ. Ici, nous utilisons la méthode du fichier local pour le configurer (vous pouvez également le remplir directement et le configurer sur la plateforme. Le mnémonique est configuré après le chiffrement, pas en texte brut).

Placez-le dans le répertoire du dossier ID du disque réel sous le répertoire du dépositaire. Bien entendu, il peut également être placé dans d’autres répertoires (le chemin spécifique doit être écrit lors de la configuration).
Remplissez la zone d’édition mnémonique :file:///mnemonic.txt, le chemin réel correspondant est :托管者所在目录/logs/storage/594291。

function main() {
// 切换测试链的索引器地址
exchange.SetBase("https://indexer.v4testnet.dydx.exchange")
// 切换测试链的ChainId
exchange.IO("chainId", "dydx-testnet-4")
// 切换测试链的REST节点地址
exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")
// 读取账户信息测试
Log(exchange.GetAccount())
}
Lisez les informations du compte réseau de test :
{
"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
}
Je n’ai pas basculé sur le réseau de test, j’ai testé avec le réseau principal
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) + "`")
}

function main() {
// 切换测试链的索引器地址
exchange.SetBase("https://indexer.v4testnet.dydx.exchange")
// 切换测试链的ChainId
exchange.IO("chainId", "dydx-testnet-4")
// 切换测试链的REST节点地址
exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")
// 限价单,挂单
var idSell = exchange.CreateOrder("ETH_USD.swap", "sell", 4000, 0.002)
var idBuy = exchange.CreateOrder("ETH_USD.swap", "buy", 3000, 0.003)
// 市价单
var idMarket = exchange.CreateOrder("ETH_USD.swap", "buy", -1, 0.01)
Log("idSell:", idSell)
Log("idBuy:", idBuy)
Log("idMarket:", idMarket)
}

Page de l’application dYdX v4 :

Le réseau de test place deux commandes à l’avance, teste l’obtention des commandes en attente actuelles et annule les commandes.
function main() {
// 切换测试链的索引器地址
exchange.SetBase("https://indexer.v4testnet.dydx.exchange")
// 切换测试链的ChainId
exchange.IO("chainId", "dydx-testnet-4")
// 切换测试链的REST节点地址
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) + "`")
}

function main() {
// 切换测试链的索引器地址
exchange.SetBase("https://indexer.v4testnet.dydx.exchange")
// 切换测试链的ChainId
exchange.IO("chainId", "dydx-testnet-4")
// 切换测试链的REST节点地址
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) + "`")
}

function main() {
// 切换测试链的索引器地址
exchange.SetBase("https://indexer.v4testnet.dydx.exchange")
// 切换测试链的ChainId
exchange.IO("chainId", "dydx-testnet-4")
// 切换测试链的REST节点地址
exchange.IO("restApiBase", "https://dydx-testnet-api.polkachu.com")
// subAccountNumber 0 -> 128 : 20 USDC , Gas Fee 为 adv4tnt 即 dydx token
var ret = exchange.IO("transferUSDCToSubaccount", 0, 128, "adv4tnt", 20)
Log("ret:", ret)
// 切换到子账号subAccountNumber 128 ,读取账户信息检查
exchange.IO("subAccountNumber", 128)
var account = exchange.GetAccount()
Log("account:", account)
}

Passez au sous-compte dont le subAccountNumber est 128 et les données renvoyées par GetAccount sont :
{
"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
}
On peut voir que le sous-compte avec le sous-compte numéro 128 a transféré 20 USDC.
Selon la commande, obtenez TxHash et testez la méthode d’appel IO du nœud REST
Comment obtenir le TxHash d’une commande ? L’objet d’échange dydx mettra en cache le TxHash, qui peut être interrogé à l’aide de l’ID de commande. Cependant, une fois la stratégie arrêtée, la carte de hachage de l’ordre tx mis en cache sera effacée.
function main() {
// 切换测试链的索引器地址
exchange.SetBase("https://indexer.v4testnet.dydx.exchange")
// 切换测试链的ChainId
exchange.IO("chainId", "dydx-testnet-4")
// 切换测试链的REST节点地址
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)
// 清空映射表可以使用: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)
}
}

Messages interrogés via TxHash :
var ret = exchange.IO(“api”, “GET”, “/cosmos/tx/v1beta1/txs/” + txHash)
Le contenu est trop long, voici donc quelques extraits pour démonstration :
{
"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": []
},
...
Les tests ci-dessus sont basés sur le dernier dépositaire. Vous devez télécharger le dernier dépositaire pour prendre en charge dYdX v4 DEX
Merci pour votre soutien et merci de votre lecture.