DEX取引所クオンツ実践(1)―dYdX v4 使用ガイド

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

[TOC]

DEX取引所クオンツ実践(1)―dYdX v4 使用ガイド

はじめに

分散型取引所(DEX)が暗号資産取引分野で急成長する中、クオンタムトレーダーは効率的な自動取引を行うため、これらのプラットフォームへの移行を進めています。dYdXは最も人気のある分散型取引プラットフォームの一つで、強力な取引機能を提供し、パーペチュアル契約取引をサポートしています。最新バージョンv4ではパフォーマンスとユーザーエクスペリエンスがさらに最適化され、多くのクオンタムトレーダーの第一選択肢となっています。

本稿ではdYdX v4におけるクオンタム取引の実践方法について解説します。APIを使用した取引実行、マーケットデータ取得、アカウント管理などを含みます。

  • テスト環境切り替え
  • マーケット情報照会
  • 注文情報・ポジション情報照会
  • 注文発注
  • サブアカウント管理
  • ノードメソッドリクエスト

dYdX v4 DEX

  • dYdXテストネットApp画面

DEX取引所クオンツ実践(1)―dYdX v4 使用ガイド

  • dYdX v3と同様、取引によりdYdXトークンの報酬が発生します。

DEX取引所クオンツ実践(1)―dYdX v4 使用ガイド

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

従来のdYdX v3プロトコルDEX取引所はサービス終了し、現在のdYdX v4 Appアドレスは以下:

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

App画面を開くと右上にウォレット接続ボタンが表示されます。QRコードをスキャンしてウォレットを接続します。

テストネット環境で事前にテストしたい場合は以下を使用:

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

同様に右上のウォレット接続ボタンからQRコードをスキャンし、署名検証を行います。ウォレット接続が成功すると自動的にdydx v4アドレスが生成され、App画面右上に表示されます。アドレスをクリックすると入金・出金・送金などの操作メニューが表示されます。dYdXメインネット(本番環境)とテストネットの主な違いの一つは、テストネットで入金をクリックすると自動的に300 USDCがテスト用に付与される点です。実際の取引を行う場合はUSDC資産を入金する必要があります。入金は様々な資産・チェーンに対応しており簡便です。

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

  • ニーモニックフレーズ 右上メニューの「パスフレーズをエクスポート」ボタンから現行dYdXアドレスアカウントのニーモニックフレーズをエクスポート可能です。FMZプラットフォームに取引所を追加する際、このニーモニックフレーズの設定が必要です。

ニーモニックフレーズはFMZプラットフォームに直接設定するか、ホストマシンに保存可能です。dydx v4取引所オブジェクト使用時にはニーモニックフレーズが記録されたファイル内容を読み取ります。本稿の実践セクションで実演します。

メインネット・テストネットの差異

テストネット環境は一部の点でメインネット環境と異なります。主な差異を以下に列挙します。

  • サブアカウント資産振替 メインネットではsubAccountNumber >= 128の場合、当該IDのサブアカウントにポジションが存在しないと資産が自動的にsubAccountNumber 0のサブアカウントに振り替えられます。 テストネットではこのメカニズムが存在しない(またはトリガー条件が異なる)ことがテストで確認されています。

  • 特定トークン名称 ネイティブトークンdydxの命名差異:メインネットDYDX、テストネットDv4TNT

  • アドレス設定(チェーンID、ノードアドレス、インデクサーアドレス等) ノードと設定は多数存在しますが、主要なものを列挙:

    • メインネット: インデクサーアドレス: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プロトコルはcosmosエコシステム上に開発されています。dYdX v4 DEXシステムの取引関連コンポーネントは主に2つで構成されます:

  • マーケット情報・アカウント情報照会を担当するインデクサー
  • dydxブロックチェーン上の注文メッセージ・注文取消メッセージ・送金メッセージ等

インデクサー

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

  • RESTプロトコル RESTプロトコルインターフェースはマーケット情報照会、アカウント情報、ポジション情報、注文情報照会などをサポートします。FMZプラットフォームでは統一APIインターフェースとして既にパッケージ化されています。

  • Websocketプロトコル FMZプラットフォームではDial関数を使用して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() {
    // 本番環境: wss://indexer.dydx.trade/v4/ws
    // テスト環境: wss://indexer.v4testnet.dydx.exchange/v4/ws

    var symbol = "ETH-USD"
    var manager = dYdXIndexerWSconnManager("wss://indexer.dydx.trade/v4/ws")
```jpn_Jpan
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プロトコルの推奨に基づき:

    // 売りの場合はオラクル価格 -5%、買いの場合はオラクル価格 +5%を推奨

    真の成行注文ではないため、オラクル価格に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は分離ポジション取引用に割り当てられ、最低20USDCの資産が必要です。 例:subAccountNumber 0 -> 128間の振替、またはsubAccountNumber 128 -> 0間の振替が可能です。振替にはGas Feeが発生し、USDCまたはdydxトークンで支払えます。

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

前節で基本的なカプセル化の詳細を説明しました。本節では具体的な実装プロセスを実践的に検証します。ここではdYdX v4テストネットを使用してデモンストレーションを行います。テストネットはメインネットとほぼ同一の構成を持ち、自動フォーセット機能でテスト資産を取得可能です。ホスティングノードのデプロイ手順は既知のため割愛し、FMZ上での実戦テスト作成に焦点を当てます。

1、設定

暗号通貨ウォレット(本稿ではimTokenウォレット使用)でdYdX v4 Appに接続後、テスト資産を取得し、現在のdYdX v4アカウント(ウォレット派生)のシードフレーズをエクスポートします。

DEX取引所クオンツ実践(1)―dYdX v4 使用ガイド

FMZプラットフォームにシードフレーズを設定します(ローカルファイル方式を採用。平文ではなく暗号化された状態でプラットフォームに設定されます)。

  • シードフレーズファイル:mnemonic.txt

DEX取引所クオンツ実践(1)―dYdX v4 使用ガイド

ホスティングノードディレクトリの実戦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])
    }
```js
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: "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: "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")

    // サブアカウント番号0 -> 128 : 20 USDC転送、Gas Feeはadv4tnt(dydxトークン)
    var ret = exchange.IO("transferUSDCToSubaccount", 0, 128, "adv4tnt", 20)  
    Log("ret:", ret)

    // サブアカウント番号128に切り替え、アカウント情報を確認
    exchange.IO("subAccountNumber", 128)

    var account = exchange.GetAccount()
    Log("account:", account)
}

DEX取引所クオンツ実践(1)―dYdX v4 使用ガイド

サブアカウント番号128に切り替えた後のGetAccount戻り値:

(JSON構造は変更なし)

サブアカウント番号128のアカウントに20USDCが転送されたことが確認できます。

8. TxHashの取得とRESTノードインターフェースの呼び出し

注文に基づくTxHash取得とRESTノード呼び出しのテスト方法

注文のTxHash取得方法:取引所オブジェクトdydxはTxHashをキャッシュしており、注文IDで照会可能。ただし戦略停止後はキャッシュされた注文txハッシュマッピングがクリアされます。

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

完了

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

ご利用ありがとうございます。お読みいただき感謝申し上げます。