Die Ressourcen sind geladen. Beförderung...

Quantitative Praxis der DEX-Börsen (1) -- dYdX v4 Benutzerhandbuch

Schriftsteller:FMZ~Lydia, Erstellt: 2024-12-26 15:32:24, aktualisiert: 2024-12-26 17:36:31

Vorwort

Mit dem rasanten Aufstieg dezentraler Börsen (DEX) im Bereich des Kryptowährungshandels haben sich quantitative Händler allmählich für einen effizienten automatisierten Handel an diese Plattformen gewandt. Als eine der beliebtesten dezentralen Handelsplattformen bietet dYdX leistungsstarke Handelsfunktionen und unterstützt den Handel mit Futures perpetual contract.

In diesem Artikel wird erläutert, wie man den quantitativen Handel auf dYdX v4 praktiziert, einschließlich der Verwendung seiner API zum Handel, zur Erfassung von Marktdaten und zur Verwaltung von Konten.

  • Wechseln der Prüfumgebung
  • Marktinformationsanfrage
  • Bestellinformationen und Positionsinformationen
  • Bestellen
  • Verwaltung von Unterkonten
  • Anforderung der Knotenmethode

dYdX v4 DEX

  • dYdX Testnet App Seite

img

  • AlsdYdX v3Mit Ethereum generiert der Handel Belohnungen, die Belohnung sinddYdX tokens.

Wallet-Verbindung, Anmeldung und Konfigurationsinformationen

Der vorherige dYdX v3 Protokoll DEX Austausch war offline. Die aktuelle dYdX v4 App-Adresse ist:

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

Nach dem Öffnen der App-Seite befindet sich in der oberen rechten Ecke eine Schaltfläche zur Verbindung zur Brieftasche.

Wenn Sie sich zunächst mit der Testnetzwerkumgebung vertraut machen möchten, können Sie das Testnetzwerk verwenden:

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

Außerdem klicken Sie auf die Schaltfläche "Connect Wallet" in der oberen rechten Ecke, scannen den Code, um die Brieftasche zu verbinden, und überprüfen Sie die Signatur. Nachdem die Brieftasche erfolgreich verbunden ist, wird automatisch eine dydx v4-Adresse generiert. Diese Adresse wird in der oberen rechten Ecke der App-Seite angezeigt. Klicken Sie darauf und ein Menü erscheint. Es gibt Operationen wie Aufladen, Abheben und Übertragen. Einer der Unterschiede zwischen dem dYdX-Mainnet (Produktionsumfeld) und dem Testnet besteht darin, dass, wenn Sie auf das Testnet klicken, 300 USDC-Assets automatisch mit dem Wasserhahn für das Testen aufgeladen werden. Wenn Sie echte Transaktionen auf dYdX durchführen möchten, müssen Sie USDC-Assets aufladen. Recharge ist auch sehr praktisch und mit mehreren Assets und Ketten für die Aufladung kompatibel.

  • dYdX v4-Kontoadresse Die dYdX v4-Kontoadresse wird aus der Wallet-Adresse abgeleitet.dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx, die eine Adresse ist, die mit dydx1 beginnt. Diese Adresse kann in Blockchain-Explorern abgerufen werden.

  • Mnemonik Sie können die Schaltfläche Export Password in der oberen rechten Ecke des Menüs verwenden, um die Mnemonik des aktuellen dYdX-Adresskontos zu exportieren.

Mnemonik kann direkt auf der FMZ-Plattform konfiguriert oder lokal auf dem Docker gespeichert werden.

Unterschiede zwischen Mainnet und Testnet

Die Testnet-Umgebung unterscheidet sich in einigen Aspekten von der Mainnet-Umgebung.

  • Vermögensübertragung auf ein Unterkonto. Das Hauptnetzwerk hat einen Mechanismus zur Bereinigung von Unterkonten.subAccountNumber >= 128, wenn das Teilkonto der ID keine Positionen hat, werden die Vermögenswerte automatisch auf das Teilkonto, dessen Teilkontonummer 0 ist, abgebucht. Bei der Prüfung wurde festgestellt, dass das Prüfnetz dieses Mechanismus nicht besitzt (oder die Auslösungsbedingungen sind unterschiedlich und es wurde im Prüfnetz nicht ausgelöst).
  • Bestimmte Symbolnamen. Das native Token dydx hat verschiedene Namen: mainnetDYDX, TestnetzDv4TNT
  • Adresskonfiguration, wie z. B. Ketten-ID, Knotenadresse, Indexadresse usw. Es gibt viele Knoten und Konfigurationen, hier ist einer von ihnen:

Hauptnetz: Indexadresse:https://indexer.dydx.tradeKette-ID:dydx-mainnet-1REST-Knoten:https://dydx-dao-api.polkachu.com:443

Testnetz: Indexadresse:https://indexer.v4testnet.dydx.exchangeKette-ID:dydx-testnet-4REST-Knoten:https://dydx-testnet-api.polkachu.com

dYdX v4 Protokollarchitektur

Das dYdX v4-Protokoll basiert auf dem Kosmos-Ökosystem. Das dYdX v4-DEX-System besteht hauptsächlich aus zwei Teilen:

  • Ein Indexer, der für die Abfrage von Tickerinformationen, Kontoinformationen usw. verantwortlich ist.
  • Dydx-Blockchain-Bestellnachrichten, Stornierungsnachrichten, Überweisungsnachrichten usw.

Indexator

Der Indexerdienst stellt REST- und Websocket-Protokolle bereit.

  • REST-Protokoll Die REST-Protokollschnittstelle unterstützt Marktinformationsanfragen, Kontoinformationen, Positionsinformationen, Auftragsinformationen und andere Anfragen und wurde als einheitliche API-Schnittstelle auf der FMZ-Plattform eingekapselt.

  • WebSocket-Protokoll Auf der FMZ-Plattform können Sie die Dial-Funktion verwenden, um eine Websocket-Verbindung zu erstellen und Marktinformationen zu abonnieren.

Es sollte beachtet werden, dass der Indexer von dydx v4 das gleiche Problem wie zentrale Börsen hat, dh Datenaktualisierungen sind nicht so zeitnah. Zum Beispiel können Sie manchmal die Bestellung nicht finden, wenn Sie sie sofort nach der Bestellung abfragen.Sleep(n)) bestimmte Vorgänge vor der Abfrage.

Hier ist ein Beispiel für die Verwendung der Dial-Funktion zur Erstellung einer Websocket-API-Verbindung und zum Abonnieren von Bestellbuchdaten:

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 Nachrichtensendung

Die am häufigsten verwendeten Nachrichten in Transaktionen sind Auftragsnachrichten, Auftragsunterbrechungsnachrichten und Überweisungsnachrichten.

  • Zusammenfassung der Bestellnachricht
{
  "@type": "/dydxprotocol.clob.MsgPlaceOrder",
  "order": {
    "orderId": {
      "subaccountId": {
        "owner": "xxx"
      },
      "clientId": xxx,
      "orderFlags": 64,
      "clobPairId": 1
    },
    "side": "SIDE_BUY",
    "quantums": "2000000",
    "subticks": "3500000000",
    "goodTilBlockTime": 1742295981
  }
}
  • Grenzfolge: In der auf der FMZ-Plattform verkapselten Orderfunktion beträgt der für Limitorders verwendete Wert orderFlags:ORDER_FLAGS_LONG_TERM = 64 # Long-term orderGemäß den Einschränkungen des DYDX v4-Protokolls wird die längste Bestelldauer von 90 Tagen verwendet (alle Bestelltypen auf DYDX v4 haben Gültigkeitsfristen).

  • Marktordnung: In der auf der FMZ-Plattform verkapselten Auftragsfunktion beträgt der für Marktordern verwendete Wert von orderFlags:ORDER_FLAGS_SHORT_TERM = 0 # Short-term order, gemäß den Empfehlungen des dydx v4-Protokolls:

// empfehlen Sie auf Oracle Preis - 5% oder niedriger für SELL, Oracle Preis + 5% für BUY

Da es sich nicht um einen echten Markt Auftrag handelt, wird der Oracle-Preis verwendet, plus oder minus 5% Slippage als Markt Auftrag. Die Gültigkeitsdauer von kurzfristigen Aufträgen unterscheidet sich auch von der von langfristigen Aufträgen. Kurzfristige Aufträge verwenden die Blockhöhe Gültigkeitsdauer, die gemäß der Empfehlung von dydx v4 auf den aktuellen Block + 10 Blockhöhen festgelegt ist.

  • Auftragsnummer: Da der Auftragsvorgang direkt in der Kette ausgeführt wird, wird nach der Übertragung der Nachricht keine vom Indexer generierte Auftrags-ID erzeugt, und die Indexer-Order kann nicht als Rückgabewert der Plattform-Auftragsfunktion verwendet werden.

Handelspaare DYDX-Kontoadresse Unterkontonummer (Unterkontonummer) ClientId (zufällig generiert) clobPairId (Id des Transaktionssymbols) AnordnungFlaggen goodTilData (Millisekunden)

  • Zusammenfassung der Nachricht zur Stornierung der Bestellung
{
  "@type": "/dydxprotocol.clob.MsgCancelOrder",
  "orderId": {
    "subaccountId": {
      "owner": "xxx"
    },
    "clientId": 2585872024,
    "orderFlags": 64,
    "clobPairId": 1
  },
  "goodTilBlockTime": 1742295981
}

Die von der FMZ-Plattform-Order-Schnittstelle zurückgegebene Order-ID muss eingegeben werden.

  • Zusammenfassung der Übertragungsnachricht
{
  "@type": "/dydxprotocol.sending.MsgCreateTransfer",
  "transfer": {
    "sender": {
      "owner": "xxx"
    },
    "recipient": {
      "owner": "xxx",
      "number": 128
    },
    "amount": "10000000"
  }
}

Der Sub-Account mit SubAccountNumber 0 ist der erste automatisch erstellte Sub-Account. Die Sub-Account-ID mit SubAccountNumber größer oder gleich 128 wird für den isolierten Positionshandel verwendet, der mindestens 20 USDC-Assets erfordert. Sie können beispielsweise von SubAccountNumber 0 -> 128 oder von SubAccountNumber 128 -> 0 gehen. Überweisungen erfordern eine Gasgebühr. Die Gasgebühr kann USDC oder dydx Token sein.

FMZ-Plattform dYdX v4 Übung

Der obige Inhalt erläutert einige Packaging-Details kurz. Als nächstes werden wir die spezifische Verwendung üben. Hier verwenden wir das dYdX v4 Testnetzwerk zur Demonstration. Das Testnetzwerk ist im Grunde das gleiche wie das Hauptnetzwerk und es gibt einen automatischen Wasserhahn zum Empfangen von Testvermögen. Der Docker-Bereitstellungsvorgang wird nicht wiederholt. Erstellen Sie einen Live-Trading-Test auf FMZ.

1. Aufbau

Nach erfolgreicher Verbindung mit der dYdX v4-App mit einer Kryptowährungsgeldbörse (hier verwende ich die imToken-Geldbörse) fordern Sie Ihre Testwerte an und exportieren Sie dann die Mnemonik für Ihr aktuelles dYdX v4-Konto (abgeleitet aus Ihrer Brieftasche).

img

Hier verwenden wir die lokale Datei-Methode, um sie zu konfigurieren (Sie können sie auch direkt ausfüllen und auf die Plattform konfigurieren).

  • Mnemonische Datei: mnemonic.txt

img

Natürlich kann es auch in andere Verzeichnisse platziert werden (der spezifische Pfad muss während der Konfiguration geschrieben werden).

  • Konfigurieren des Austauschs auf FMZ

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

Füllen Sie das mnemonische Bearbeitungsfeld aus:file:///mnemonic.txt, ist der entsprechende tatsächliche Weg:docker directory/logs/storage/594291.

img

2. Wechseln Sie zum dydx v4 Testnetzwerk

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

Lesen Sie die Testnetzwerk-Kontoinformationen:

{
	"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. Marktinformationsuntersuchung

Nicht auf das Testnetz umgestellt, mit dem Hauptnetz getestet

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. Bestellen

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 App Seite:

img

5. Bestellinformationen

Das Testnetzwerk legt zwei Aufträge im Voraus auf, testet die aktuellen ausstehenden Aufträge und storniert die Aufträge.

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. Nachfrage nach Stelleninformationen

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. Verwaltung von Unterkonten

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

Daten des Protokolls:

img

Wechseln Sie zum Unterkonto, dessen Unterkontonummer 128 ist, und die von GetAccount zurückgegebenen Daten sind:

{
	"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
}

Man sieht, dass das Unterkonto mit Unterkonto Nummer 128 20 USDC überwiesen hat.

8. Holen Sie sich TxHash und rufen Sie die REST Node Interface

Entsprechend der Reihenfolge, erhalten TxHash und testen Sie die Methode der IO REST Knoten rufen

Wie bekommt man den TxHash einer Bestellung? Das Exchange-Objekt dydx speichert den TxHash, der mit der Order-ID abgerufen werden kann.

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

Nachrichten, die über TxHash abgefragt wurden:

VAR RET =exchange.IO(Api, GET, /cosmos/tx/v1beta1/txs/ + txHash)

Der Inhalt ist zu lang, also hier einige Auszüge zur Demonstration:

{
	"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": []
			},
      ...

Das Ende

Die oben genannten Tests basieren auf dem neuesten Docker. Sie müssen den neuesten Docker herunterladen, um dYdX v4 DEX zu unterstützen

Vielen Dank für Ihre Unterstützung und für das Lesen.


Mehr