資源の読み込みに... 荷物...

DEX取引所の定量実践 (1) -- dYdX v4 ユーザーガイド

作者: リン・ハーンFMZ~リディア作成日:2024年12月26日 15:32:24 更新日:2024年12月26日 17:36:31

前言

仮想通貨取引における分散型取引所 (DEX) の急速な増加により,定量トレーダーは効率的な自動取引のために徐々にこれらのプラットフォームに目を向けています.最も人気のある分散型取引プラットフォームの1つとして,dYdXは強力な取引機能を提供し,先物永続契約取引をサポートしています.最新バージョンv4はパフォーマンスとユーザー体験を最適化し,多くの定量トレーダーにとって最初の選択となっています.

この記事では,dYdX v4 で定量取引を実践する方法,そのAPI を取引,市場データを取得,アカウントを管理するために使用する方法などを紹介します.

  • 試験環境の切り替え
  • 市場情報検索
  • 注文情報と位置情報検索
  • 注文する
  • サブアカウント管理
  • ノードメソッド要求

dYdX v4 DEX

  • dYdXテストネット アプリページ

img

  • そのようにdYdX v3取引は報酬を生み出しますdYdX tokens.

ウォレット接続,ログイン,設定情報

以前の dYdX v3 プロトコル DEX 交換はオフラインでした.現在の dYdX v4 アプリアドレス:

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

アプリのページを開くと,右上の角にウォレットに接続するボタンが表示されます. QRコードをスキャンしてウォレットに接続します.

まずテストネットワーク環境をテストし 熟知したい場合は,テストネットワークを使用できます.

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

また,右上隅にあるコネクトウォレットボタンをクリックし,ウォレットに接続するコードをスキャンし,署名を確認します.ウォレットが成功して接続された後, dydx v4 アドレスは自動的に生成されます.このアドレスはアプリページの右上隅に表示されます.クリックするとメニューがポップアップします.リチャージ,引き出し,転送などの操作があります. dYdX メインネット (生産環境) とテストネットの違いの1つは,テストネットでリチャージをクリックすると,300 USDCの資産が自動的にテスト用のタップを使用して充電されます.dYdXで実際のトランザクションを行う場合は,USDCの資産を充電する必要があります.リチャージは,リチャージのための複数の資産やチェーンにも非常に便利で互換性があります.

  • dYdX v4 アカウント アドレス dYdX v4 アカウント アドレスはウォレット アドレスから派生します. dYdX v4 アカウント アドレスは次のように見えます:dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxxこのアドレスはブロックチェーン エクスプローラーでクエリできます.

  • 覚醒術 現在の dYdX アドレス アカウントのメモニックをエクスポートするには,右上隅のメニューにある Export Password ボタンを使用できます. FMZ プラットフォームに交換を追加する際には,このメモニックを設定する必要があります.

メネモニックは,FMZプラットフォーム上で直接設定したり,ドッカー上でローカルに保存したりできます. dydx v4交換オブジェクトを使用すると,この記事の実践部分で示されるような,メモニックを記録するファイルのコンテンツが読み取れます.

メインネットとテストネットの違い

テストネット環境は メインネット環境とはいくつかの点で異なります.いくつかの単純な違いがあります.

  • サブ口座への資産移転 主なネットワークにはサブアカウントのクリーンアップメカニズムがあります.subAccountNumber >= 128IDのサブアカウントにポジションがない場合は,資産は自動的にサブアカウントにクリアされます.そのサブアカウント番号は0です. テスト中に,テストネットワークにこのメカニズムがないことが判明した (またはトリガー条件が異なっており,テストネットワークでトリガーされていない).
  • 特定のシンボル名 ネイティブ・トークン dydx は異なる名前があります: mainnetDYDXテストネットDv4TNT
  • チェーンID,ノードアドレス,インデクサーアドレスなど,アドレス構成 複数のノードと構成があります.

メインネット: インデクサー アドレス:https://indexer.dydx.tradeチェーンID:dydx-mainnet-1RESTノード:https://dydx-dao-api.polkachu.com:443

テストネット: インデクサー アドレス:https://indexer.v4testnet.dydx.exchangeチェーンID:dydx-testnet-4RESTノード:https://dydx-testnet-api.polkachu.com

dYdX v4 プロトコル アーキテクチャ

dYdX v4プロトコルは,cosmosエコシステムに基づいて開発されている. dYdX v4 DEX システムのトランザクション関連コンテンツは主に2つの部分で構成されている:

  • チケット情報,口座情報などをクエリするインデクサー
  • dydx ブロックチェーンの注文メッセージ,注文キャンセルメッセージ,転送メッセージなど

インデクサー

インデクサーサービスは REST と Websocket プロトコルを提供します.

  • REST プロトコル RESTプロトコルのインターフェースは,市場情報クエリ,アカウント情報,ポジション情報,オーダー情報およびその他のクエリをサポートし,FMZプラットフォーム上で統一されたAPIインターフェースとして封筒化されています.

  • WebSocket プロトコル FMZプラットフォームでは,Webソケット接続を作成し,市場情報へのサブスクリプションを Dial 機能でできます.

dydx v4 のインデクサーは,集中取引所と同じ問題があることに注意すべきです.つまり,データ更新はそれほどタイムリーではありません.例えば,注文を注文した直後にクエリした場合,時には注文を見つけることができない場合があります.注文後数秒待つことが推奨されます (Sleep(n)) 問い合わせの前に特定の操作を行う.

Websocket API 接続を作成し,オーダーブックデータにサブスクリプトする Dial 関数を使用する例です.

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 チェーンノード メッセージ ブロードキャスト

トランザクションで最も一般的に使用されるメッセージは,注文メッセージ,注文キャンセルメッセージ,および転送メッセージです.

  • 注文メッセージの要約
{
  "@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 orderdydx v4 プロトコルの制限により,最長注文有効期間が 90 日 ( dydx v4 のすべてのタイプの注文には有効期間があります) で使用されます.

  • 市場順序 FMZプラットフォームに収縮されたオーダー関数では,市場オーダーに使用されるorderFlags値は:ORDER_FLAGS_SHORT_TERM = 0 # Short-term orderDYDX v4 プロトコルの推奨に従って

// オラクル価格に設定する推奨 - SELL の場合は5%以下,ORACLE の場合は5%以下

市場オーダーとは違うため,オラクル価格,プラスまたはマイナス5%のスリップが市場オーダーとして使用される.短期オーダーの有効期限は長期オーダーの有効期限とは異なる.短期オーダーは,現在のブロック+10ブロックの高さに設定されたブロック高さの有効期間を使用する. dydx v4の推奨に従って,短期オーダーは,現在のブロック+10ブロック高さに設定される.

  • 注文番号: オーダー操作はチェーン上で直接実行されるため,メッセージが送信された後にインデクサーによって生成されるオーダーIDはなく,インデクサーオーダーはプラットフォームオーダー関数の返却値として使用することはできません.オーダーIDのユニーク性とオーダークエリの正確性を確保するために,返されたオーダーIDは以下の情報 (コンマで分離) から構成されます:

トレーディングペア dydx 現金口座の住所 サブアカウント番号 (サブアカウント番号) clientId (ランダム生成) clobPairId (トランザクションシンボルのID) 順序 フラグ goodTilData (ミリ秒)

  • 注文キャンセルメッセージの要約
{
  "@type": "/dydxprotocol.clob.MsgCancelOrder",
  "orderId": {
    "subaccountId": {
      "owner": "xxx"
    },
    "clientId": 2585872024,
    "orderFlags": 64,
    "clobPairId": 1
  },
  "goodTilBlockTime": 1742295981
}

FMZ プラットフォームの注文インターフェイスから返された注文IDを入力する必要があります.

  • 転送メッセージ要約
{
  "@type": "/dydxprotocol.sending.MsgCreateTransfer",
  "transfer": {
    "sender": {
      "owner": "xxx"
    },
    "recipient": {
      "owner": "xxx",
      "number": 128
    },
    "amount": "10000000"
  }
}

現在の dydx v4 アドレスで多くのサブアカウントを作成できます.サブアカウント番号0のサブアカウントは,自動的に作成された最初のサブアカウントです.サブアカウント番号が 128 以上または等しいサブアカウントIDは,少なくとも 20 USDC の資産を必要とする孤立したポジション取引に使用されます. たとえば,サブアカウント番号0 -> 128 から,またはサブアカウント番号128 -> 0 から,送金にはガス料金がかかります.ガス料金はUSDCまたは dydxトークンです.

FMZ プラットフォーム dYdX v4 練習

上記のコンテンツは,いくつかのパッケージの詳細を簡潔に説明しています.次に,具体的な使用を実践してみましょう.ここでデモのためにdYdX v4テストネットワークを使用します.テストネットワークは基本的にメインネットワークと同じで,テスト資産を受け取るための自動水槽があります.ドッカー展開操作は繰り返されません. FMZでライブ取引テストを作成します.

1. 構成

dYdX v4 アプリに暗号通貨のウォレット (ここでは imToken ウォレットを使用しています) を使って成功して接続した後,テスト資産を請求し,現在の dYdX v4 アカウント (ウォレットから派生した) のメモニックをエクスポートします.

img

FMZ プラットフォームでメモニックを設定します. ここではローカルファイルメソッドを使用して設定します (直接記入してプラットフォームに設定することもできます.メモニックは暗号化後に設定されます. 文本ではありません).

  • メネモニックファイル: mnemonic.txt

img

DOCKER ディレクトリの下のライブ取引IDフォルダに配置します. もちろん,他のディレクトリにも配置できます (設定中に特定のパスを書く必要があります).

  • 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. 注文情報

テストネットワークは2つの注文を事前に実行し,現在待機中の注文をテストし,注文をキャンセルします.

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
}

サブアカウント番号128のサブアカウントで 20ドルを転送したことがわかります

8. TxHash を取得し,REST ノード インターフェースを呼び出します

REST ノードを呼び出す IO の方法をテストします.

注文の TxHash を取得するには?交換オブジェクト dydx は TxHash をキャッシュし,注文 ID を使用してクエリすることができます.しかし,戦略が停止された後,キャッシュされた注文 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 で問い合わせたメッセージ:

バール=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 をサポートするために最新のドッカーをダウンロードする必要があります.

応援してくれて ありがとう


もっと