Les ressources ont été chargées... Je charge...

Pratique quantitative des échanges DEX (1) -- Guide de l'utilisateur dYdX v4

Auteur:FMZ~Lydia, Créé: 2024-12-26 15:32:24, Mis à jour: 2024-12-26 17:36:31

Préface

Avec l'essor rapide des bourses décentralisées (DEX) dans le domaine du trading de crypto-monnaie, les traders quantitatifs se sont progressivement tournés vers ces plateformes pour un trading automatisé efficace.

Cet article présentera comment pratiquer le trading quantitatif sur dYdX v4, y compris comment utiliser son API pour trader, obtenir des données de marché et gérer des comptes.

  • Changement d'environnement d'essai
  • Demande d'informations sur le marché
  • Demande d'informations de commande et de position
  • Faites une commande
  • Gestion des sous-comptes
  • Demande de méthode de nœud

Le système d'exploitation de l'appareil doit être configuré de manière à ce qu'il soit compatible avec le système d'exploitation.

  • Page de l'application du testnet dYdX

img

  • CommedYdX v3Avec Ethereum, le trading génère des récompenses, qui sont des récompensesdYdX tokens.

Connexion, connexion et configuration du portefeuille

L'échange DEX précédent du protocole dYdX v3 a été désactivé. L'adresse actuelle de l'application dYdX v4 est:

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

Après avoir ouvert la page de l'application, il y a un bouton pour se connecter au portefeuille dans le coin supérieur droit. Scannez le code QR pour se connecter au portefeuille.

Si vous voulez tester et vous familiariser avec l'environnement du réseau de test en premier, vous pouvez utiliser le réseau de test:

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

En outre, cliquez sur le bouton de connexion du portefeuille dans le coin supérieur droit, scannez le code pour connecter le portefeuille et vérifiez la signature. Une fois le portefeuille connecté avec succès, une adresse dydx v4 sera générée automatiquement. Cette adresse sera affichée dans le coin supérieur droit de la page de l'application. Cliquez dessus et un menu apparaîtra. Il existe des opérations telles que la recharge, le retrait et le transfert.

  • Adresse du compte dYdX v4 L'adresse du compte dYdX v4 est dérivée de l'adresse du portefeuille.dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx, qui est une adresse commençant par dydx1.

  • Mnémonique Vous pouvez utiliser le bouton Exporter mot de passe dans le menu du coin supérieur droit pour exporter les mnémoniques du compte d'adresse dYdX en cours.

Les mnémoniques peuvent être configurées directement sur la plate-forme FMZ ou enregistrées localement sur le docker.

Différences entre le Mainnet et le Testnet

L'environnement testnet est différent de l'environnement mainnet à certains égards.

  • Transfert d'actifs sur un sous-compte. Le réseau principal a un mécanisme de nettoyage des sous-comptes.subAccountNumber >= 128, si le sous-compte de l'ID n'a pas de positions, les actifs seront automatiquement nettoyés sur le sous-compte dont le sous-compteNumber est 0. Au cours des essais, il a été constaté que le réseau d'essai ne possède pas ce mécanisme (ou que les conditions de déclenchement sont différentes et qu'il n'a pas été déclenché dans le réseau d'essai).
  • Certains noms symboliques. Le jeton natif dydx a des noms différents: mainnetDYDXRéseau d'essaiDv4TNT
  • Configuration de l'adresse, telle que l'identifiant de chaîne, l'adresse du nœud, l'adresse de l'indexateur, etc. Il y a beaucoup de nœuds et de configurations, voici l'un d'entre eux:

Réseau principal: Adresse de l' indexeur:https://indexer.dydx.tradeIdentifiant de la chaîne:dydx-mainnet-1Nœud REST:https://dydx-dao-api.polkachu.com:443

Réseau de test: Adresse de l' indexeur:https://indexer.v4testnet.dydx.exchangeIdentifiant de la chaîne:dydx-testnet-4Nœud REST:https://dydx-testnet-api.polkachu.com

L'architecture du protocole dYdX v4

Le protocole dYdX v4 est développé sur la base de l'écosystème cosmos.

  • Un indexeur chargé de rechercher des informations sur les tickers, les informations sur les comptes, etc.
  • les messages de commande de la chaîne de blocs dydx, les messages d'annulation de commande, les messages de transfert, etc.

Indicateur

Le service d'indexation fournit des protocoles REST et Websocket.

  • Protocole REST L'interface de protocole REST prend en charge la requête d'informations sur le marché, les informations sur les comptes, les informations de position, les informations sur les commandes et d'autres requêtes, et a été encapsulée comme une interface API unifiée sur la plateforme FMZ.

  • Protocole WebSocket Sur la plateforme FMZ, vous pouvez utiliser la fonction Dial pour créer une connexion Websocket et vous abonner aux informations de marché.

Il convient de noter que l'indexeur de dydx v4 a le même problème que les échanges centralisés, c'est-à-dire que les mises à jour des données ne sont pas si opportunes. Par exemple, il se peut que vous ne puissiez pas trouver l'ordre si vous le consultez immédiatement après avoir passé une commande. Il est recommandé d'attendre quelques secondes après (Sleep(n)) certaines opérations avant la requête.

Voici un exemple d'utilisation de la fonction Dial pour créer une connexion API Websocket et souscrire aux données du carnet de commandes:

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) + "`")
    }
}

Diffusion du message de nœud de chaîne dYdX

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.

  • Résumé du message de commande
{
  "@type": "/dydxprotocol.clob.MsgPlaceOrder",
  "order": {
    "orderId": {
      "subaccountId": {
        "owner": "xxx"
      },
      "clientId": xxx,
      "orderFlags": 64,
      "clobPairId": 1
    },
    "side": "SIDE_BUY",
    "quantums": "2000000",
    "subticks": "3500000000",
    "goodTilBlockTime": 1742295981
  }
}
  • L' ordre limite: Dans la fonction d'ordre encapsulée sur la plateforme FMZ, la valeur de orderFlags utilisée pour les ordres limites est:ORDER_FLAGS_LONG_TERM = 64 # Long-term orderConformément aux limites du protocole dydx v4, la plus longue période de validité des commandes est utilisée, qui est de 90 jours (tous les types de commandes sur dydx v4 ont des périodes de validité).

  • L'ordre du marché: Dans la fonction d'ordre encapsulée sur la plateforme FMZ, la valeur de orderFlags utilisée pour les ordres de marché est:ORDER_FLAGS_SHORT_TERM = 0 # Short-term order, selon les recommandations du protocole dydx v4:

// Recommander fixé au prix oracle - 5% ou moins pour VENDRE, prix oracle + 5% pour acheter

Comme 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é. La période de validité des ordres à court terme est également différente de celle des ordres à long terme. Les ordres à court terme utilisent la période de validité de la hauteur du bloc, qui est réglée sur le bloc actuel + 10 hauteurs de bloc selon la recommandation de dydx v4.

  • Nom de la commande: Étant donné que l'opération d'ordre est effectuée directement sur la chaîne, il n'y aura pas d'identifiant d'ordre généré par l'indexateur après la diffusion du message et l'ordre d'indexateur ne peut pas être utilisé comme valeur de retour de la fonction d'ordre de la plate-forme.

Paires de négociation Adresse du compte courant dydx Numéro de sous-compte (subcompteNuméro) clientId (généré aléatoirement) clobPairId (identifiant du symbole de transaction) ordreFlags goodTilData (millièmes de seconde)

  • 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'identifiant de commande renvoyé par l'interface de commande de la plateforme FMZ doit être transmis.

  • Résumé du message de transfert
{
  "@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. Le sous-compte avec le sous-compte numéro 0 est le premier sous-compte créé automatiquement. Par exemple, vous pouvez passer du sous-compte numéro 0 -> 128 ou du sous-compte numéro 128 -> 0. Les transferts nécessitent des frais de gaz.

FMZ Plateforme dYdX v4

Le contenu ci-dessus explique brièvement certains détails de l'emballage. 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 y a un robinet automatique pour recevoir les actifs de test. L'opération de déploiement du docker ne sera pas répétée. Créez un test de trading en direct sur FMZ.

1. la configuration

Après vous être connecté à l'application dYdX v4 avec succès à l'aide d'un portefeuille de crypto-monnaie (j'utilise le portefeuille imToken ici), revendiquez vos actifs de test, puis exportez le mnémonique pour votre compte dYdX v4 actuel (dérivé de votre portefeuille).

img

Configurer le mnémonique sur la plateforme FMZ. Ici, nous utilisons la méthode de 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).

  • Fichier mnémonique mnémonique.txt

img

Bien sûr, il peut également être placé dans d'autres répertoires (le chemin spécifique doit être écrit pendant la configuration).

  • Configurer l' échange sur FMZ

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

Remplissez la zone de modification mnémonique:file:///mnemonic.txt, la trajectoire réelle correspondante est:docker directory/logs/storage/594291.

img

2. Passez au réseau de test 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()) 
}

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
}

3. Enquête sur l'information sur le marché

Ne pas passer au réseau d'essai, 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) +  "`")
}

img

4. Faire une commande

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

Page de l'application dYdX v4:

img

5. Informations sur la commande

Le réseau de test passe deux commandes à l'avance, teste les commandes en attente actuelles et annule les commandes.

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. Recherche d'informations sur le poste

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. Gestion des sous-comptes

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)
}

Informations sur le journal:

img

Passez au sous-compte dont le numéro de sous-compte 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.

8. Obtenez TxHash et appelez l'interface de nœud REST

Selon l'ordre, obtenir TxHash et tester la méthode d'IO appelant le nœud REST

Comment obtenir le TxHash d'une commande? L'objet d'échange dydx cache le TxHash, qui peut être interrogé à l'aide de l'identifiant de commande. Cependant, après l'arrêt de la stratégie, la carte de hachage d'ordre tx mis en cache sera effacée.

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

Les messages interrogés par TxHash:

Le taux de changeexchange.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": []
			},
      ...

La fin

Les tests ci-dessus sont basés sur le dernier docker. Vous devez télécharger le dernier docker pour supporter dYdX v4 DEX

Merci pour votre soutien et merci de lire.


Plus de