avatar of 发明者量化-小小梦 发明者量化-小小梦
フォロー ダイレクトメッセージ
4
フォロー
1271
フォロワー

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

作成日:: 2024-12-24 17:09:32, 更新日:: 2024-12-26 21:41:46
comments   0
hits   1049

[TOC]

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

序文

暗号通貨取引の分野で分散型取引所(DEX)が急速に普及するにつれ、定量取引を行うトレーダーは効率的な自動取引のために徐々にこれらのプラットフォームに目を向けるようになりました。最も人気のある分散型取引プラットフォームの 1 つである dYdX は、強力な取引機能を提供し、先物無期限契約取引をサポートしています。最新バージョンの v4 では、パフォーマンスとユーザー エクスペリエンスが最適化されており、多くの定量取引トレーダーにとって第一の選択肢となっています。

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

  • テスト環境の切り替え
  • 市場情報クエリ
  • 注文情報と位置情報の照会
  • 注文する
  • サブアカウント管理
  • ノードメソッドリクエスト

dYdX v4 DEX

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

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

  • そしてdYdX v3同様に、取引は報酬を生み出し、報酬はdYdXトークン。

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

ウォレットの接続、ログイン、および設定情報

以前の dYdX v3 プロトコル DEX 取引所はオフラインになっています。現在の dYdX v4 アプリのアドレスは次のとおりです:

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

アプリページを開くと、右上にウォレットに接続するためのボタンがあります。QRコードをスキャンしてウォレットに接続します。

最初にテスト ネットワーク環境をテストして理解したい場合は、テスト ネットワークを使用できます。

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

また、右上隅のウォレット接続ボタンをクリックし、QR コードをスキャンしてウォレットに接続し、署名を確認します。ウォレットが正常に接続されると、dydx v4 アドレスが自動的に生成されます。このアドレスはアプリ ページの右上隅に表示されます。クリックするとメニューがポップアップ表示されます。これらには、再チャージ、引き出し、送金などの操作が含まれます。 dYdX メインネット (実稼働環境) とテストネットの違いの 1 つは、テストネットのトップアップ ボタンをクリックすると、300 USDC 資産がテスト用に自動的にフォーセットに預けられることです。 dYdXで実際の取引を行う場合は、USDC資産を入金する必要があります。リチャージも非常に便利で、複数の資産やチェーンと互換性があります。

  • dYdX v4 アカウントアドレス dYdX v4 アカウント アドレスはウォレット アドレスから派生します。dYdX v4 アカウント アドレスは次のようになります。dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxxは、dydx1 で始まるアドレスです。このアドレスはブロックチェーンエクスプローラーで照会できます。

  • 記憶術 右上隅のメニューにある「パスワードのエクスポート」ボタンをクリックすると、現在の dYdX アドレス アカウントのニーモニックをエクスポートできます。 FMZ プラットフォームに取引所を追加する場合は、このニーモニックを設定する必要があります。

ニーモニックは、FMZ プラットフォーム上で直接設定することも、カストディアンのローカルに保存することもできます。dydx v4 交換オブジェクトを使用する場合、ニーモニックを記録したファイルの内容が読み取られます。これは、この記事の実践的な部分で示されます。

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

テストネット環境は、いくつかの点でメインネット環境とは異なります。ここでは、いくつかの簡単な違いを紹介します。

  • サブアカウント資産の移転。 メインネットワークにはサブアカウントのクリーニングメカニズムがあります。subAccountNumber >= 128この ID のサブアカウントにポジションがない場合、資産は自動的に subAccountNumber 0 のサブアカウントにクリアされます。 テスト中に、テスト ネットワークにはそのようなメカニズムがない (またはトリガー条件が異なり、テスト ネットワークではトリガーされていなかった) ことが判明しました。

  • いくつかのトークン名。 ネイティブトークンdydxは別の名前が付けられています: メインネットDYDX、テストネットワークDv4TNT

  • チェーン ID、ノード アドレス、インデクサー アドレスなどのアドレス構成。 ノードと構成は多数ありますが、そのうちの 1 つを次に示します。

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

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

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

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

  • 市場情報、アカウント情報などのクエリを担当するインデクサー。
  • dydx ブロックチェーンの注文メッセージ、注文キャンセルメッセージ、転送メッセージなど。

インデクサー

インデクサー サービスは、REST および Websocket プロトコルを提供します。

  • REST プロトコル REST プロトコル インターフェースは、市場情報のクエリ、アカウント情報、ポジション情報、注文情報などをサポートし、FMZ プラットフォーム上の統一された API インターフェースとしてカプセル化されています。

  • WebSocket プロトコル FMZ プラットフォームでは、ダイヤル機能を使用して Websocket 接続を作成し、市場情報をサブスクライブできます。

dydx v4 インデクサーには、中央集権型取引所と同じ問題、つまりデータの更新がそれほどタイムリーではないという問題があることに注意してください。たとえば、注文を行った直後にクエリを実行すると、注文が見つからない場合があります。特定の操作(Sleep(n)) 再度クエリを実行する前に数秒待ってください。

Dial 関数を使用して Websocket API 接続を作成し、注文書データをサブスクライブする例を次に示します。

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

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 # 长期订单DYDX v4 プロトコルの制限に従って、最長の注文有効期間である 90 日が使用されます (DYDX v4 のすべてのタイプの注文には有効期間があります)。

  • 成行注文: FMZ プラットフォームにカプセル化された注文関数では、市場注文で使用される orderFlags 値は次のとおりです。ORDER_FLAGS_SHORT_TERM = 0 # 短期订单DYDX v4 プロトコルの推奨事項によると、次のようになります。

    // Recommend set to oracle price - 5% or lower for SELL, oracle price + 5% for BUY

    これは真の成行注文ではないため、成行注文としてプラスマイナス 5% のスリッページを加えたオラクル価格が使用されます。短期注文の有効期間設定も長期注文とは異なります。短期注文はブロック高の有効期間を使用します。dydx v4の推奨によると、現在のブロック+10ブロック高に設定されます。期限が切れる前に。

  • 注文ID: 注文操作はチェーン上で直接実行されるため、メッセージがブロードキャストされた後にインデクサーによって生成される注文IDはなく、インデクサーの注文はプラットフォーム注文関数の戻り値として使用できません。一意性を保証するために注文 ID と注文クエリの精度に基づいて、インデクサー注文が返されます。注文 ID は次の情報で構成されます (カンマ区切り)。

    • 取引ペア
    • dydx 当座預金口座アドレス
    • サブアカウント番号 (subaccountNumber)
    • clientId (ランダムに生成)
    • clobPairId (トランザクションシンボルID)
    • orderFlags
    • 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アドレスの下には、多くのサブアカウントを作成できます。subAccountNumber 0のサブアカウントは、最初に自動的に作成されるサブアカウントです。subAccountNumberが128以上のサブアカウントIDは、独立したポジション取引に使用されます。少なくとも 20 の USDC 資産が必要です。 たとえば、subAccountNumber 0 -> 128、または subAccountNumber 128 -> 0 に移動できます。送金にはガス料金がかかります。 Gas Fee には USDC および dydx トークンを使用できます。

FMZプラットフォームdYdX v4の実践

上記の内容は、パッケージの詳細を簡単に説明したものです。次に、具体的な使用方法を実践してみましょう。ここでは、デモンストレーションにdYdX v4テストネットワークを使用します。テストネットワークは基本的にメインネットワークと同じで、テストアセットを受け取るための自動蛇口があります。管理者は、操作の詳細については説明せず、FMZ で実際のテストを作成します。

1. 構成

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

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

FMZ プラットフォームでニーモニックを設定します。ここでは、ローカル ファイル メソッドを使用して設定します (直接入力してプラットフォームに設定することもできます。ニーモニックはプレーン テキストではなく、暗号化後に設定されます)。

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

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

それを、custodian ディレクトリの下の実際のディスク ID フォルダ ディレクトリに配置します。もちろん、他のディレクトリに配置することもできます (特定のパスは構成時に記述する必要があります)。

  • FMZで交換を設定する

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

ニーモニック編集ボックスに入力します:file:///mnemonic.txt対応する実際のパスは次のようになります。托管者所在目录/logs/storage/594291

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

2. dydx v4テストネットワークに切り替える

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

テスト ネットワーク アカウント情報を読み取ります。

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

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

4. 注文する

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

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

dYdX v4 アプリページ:

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

5. 注文情報

テスト ネットワークは、事前に 2 つの注文を配置し、現在の保留中の注文の取得をテストし、注文をキャンセルします。

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

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

6. 位置情報クエリ

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

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

7. サブアカウント管理

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

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

subAccountNumber が 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
}

subAccountNumber 128 のサブアカウントが 20 USDC を送金したことがわかります。

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

指示に従ってTxHashを取得し、RESTノードを呼び出すIOメソッドをテストする

注文の TxHash を取得するにはどうすればよいでしょうか? 取引所オブジェクト dydx は TxHash をキャッシュし、注文 ID を使用して照会することができます。ただし、戦略が停止すると、キャッシュされた注文トランザクション ハッシュ マップはクリアされます。

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

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

TxHash を通じて照会されたメッセージ:

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

内容が長すぎるので、デモンストレーション用にいくつか抜粋します。

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

THE END

上記のテストは最新のカストディアンに基づいています。dYdX v4 DEXをサポートするには、最新のカストディアンをダウンロードする必要があります。

ご支援、そしてご愛読ありがとうございました。