[TOC]

Với sự gia tăng nhanh chóng của các sàn giao dịch phi tập trung (DEX) trong lĩnh vực giao dịch tiền điện tử, các nhà giao dịch định lượng đã dần bắt đầu chuyển sang các nền tảng này để giao dịch tự động hiệu quả. Là một trong những nền tảng giao dịch phi tập trung phổ biến nhất, dYdX cung cấp các chức năng giao dịch mạnh mẽ và hỗ trợ giao dịch hợp đồng tương lai vĩnh viễn. Phiên bản mới nhất v4 của nó tối ưu hóa hiệu suất và trải nghiệm người dùng, khiến nó trở thành lựa chọn đầu tiên cho nhiều nhà giao dịch định lượng.
Bài viết này sẽ giới thiệu cách thực hành giao dịch định lượng trên dYdX v4, bao gồm cách sử dụng API để giao dịch, thu thập dữ liệu thị trường và quản lý tài khoản.

dYdX v3Tương tự như vậy, các giao dịch tạo ra phần thưởng, phần thưởngdYdXMã thông báo.
Giao thức trao đổi DEX dYdX v3 trước đây đã ngoại tuyến. Địa chỉ ứng dụng dYdX v4 hiện tại là:
Sau khi mở trang Ứng dụng, có một nút để kết nối với ví ở góc trên bên phải. Quét mã QR để kết nối với ví.
Nếu bạn muốn kiểm tra và làm quen với môi trường mạng thử nghiệm trước, bạn có thể sử dụng mạng thử nghiệm:
Ngoài ra, hãy nhấp vào nút kết nối ví ở góc trên bên phải, quét mã QR để kết nối với ví và xác minh chữ ký. Sau khi ví được kết nối thành công, địa chỉ dydx v4 sẽ tự động được tạo. Địa chỉ này sẽ được hiển thị ở góc trên bên phải của trang Ứng dụng. Một menu sẽ bật lên sau khi nhấp vào. Bao gồm các hoạt động như nạp tiền, rút tiền và chuyển tiền. Một trong những điểm khác biệt giữa mạng chính dYdX (môi trường sản xuất) và mạng thử nghiệm là khi bạn nhấp vào nút nạp tiền trên mạng thử nghiệm, 300 tài sản USDC sẽ tự động được gửi vào vòi để thử nghiệm. Nếu bạn muốn thực hiện giao dịch thực tế trên dYdX, bạn cần phải gửi tài sản USDC. Nạp tiền cũng rất tiện lợi và tương thích với nhiều tài sản và chuỗi.
Địa chỉ tài khoản dYdX v4
Địa chỉ tài khoản dYdX v4 được lấy từ địa chỉ ví. Địa chỉ tài khoản dYdX v4 trông như thế này:dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx, là địa chỉ bắt đầu bằng dydx1. Địa chỉ này có thể được truy vấn trong trình khám phá blockchain.
Thuật ghi nhớ Bạn có thể xuất mã ghi nhớ của tài khoản địa chỉ dYdX hiện tại bằng cách nhấp vào nút “Xuất mật khẩu” ở menu góc trên bên phải. Khi thêm một sàn giao dịch trên nền tảng FMZ, bạn cần cấu hình mã ghi nhớ này.
Mnemonics có thể được cấu hình trực tiếp trên nền tảng FMZ hoặc được lưu cục bộ trên người giám hộ. Khi sử dụng đối tượng trao đổi dydx v4, nội dung tệp ghi lại mnemonics sẽ được đọc, điều này sẽ được trình bày trong phần thực hành của bài viết này.
Môi trường testnet khác với môi trường mainnet ở một số khía cạnh. Sau đây là một số điểm khác biệt đơn giản.
Chuyển tài sản phụ.
Mạng chính có cơ chế dọn dẹp tài khoản phụ.subAccountNumber >= 128Nếu tài khoản phụ có ID này không có vị thế nào, tài sản sẽ tự động được chuyển vào tài khoản phụ có subAccountNumber 0.
Trong quá trình thử nghiệm, người ta phát hiện ra rằng mạng thử nghiệm không có cơ chế như vậy (hoặc các điều kiện kích hoạt khác nhau và nó chưa được kích hoạt trên mạng thử nghiệm).
Một số tên mã thông báo.
Mã thông báo gốc dydx được đặt tên khác: MainnetDYDX, mạng thử nghiệmDv4TNT
Cấu hình địa chỉ, chẳng hạn như ID chuỗi, địa chỉ nút, địa chỉ lập chỉ mục, v.v. Có nhiều nút và cấu hình, đây là một trong số đó:
Mạng chính:
Địa chỉ lập chỉ mục:https://indexer.dydx.trade
ID chuỗi:dydx-mainnet-1
Nút REST:https://dydx-dao-api.polkachu.com:443
Mạng thử nghiệm:
Địa chỉ lập chỉ mục:https://indexer.v4testnet.dydx.exchange
ID chuỗi:dydx-testnet-4
Nút REST:https://dydx-testnet-api.polkachu.com
Giao thức dYdX v4 được phát triển dựa trên hệ sinh thái cosmos. Nội dung liên quan đến giao dịch của hệ thống dYdX v4 DEX chủ yếu bao gồm hai phần:
Dịch vụ lập chỉ mục cung cấp các giao thức REST và Websocket.
Giao thức REST Giao diện giao thức REST hỗ trợ truy vấn thông tin thị trường, thông tin tài khoản, thông tin vị thế, thông tin lệnh, v.v. và đã được đóng gói thành giao diện API thống nhất trên nền tảng FMZ.
Giao thức WebSocket Trên nền tảng FMZ, bạn có thể sử dụng chức năng Quay số để tạo kết nối Websocket và đăng ký nhận thông tin thị trường.
Cần lưu ý rằng dydx v4 indexer có cùng vấn đề với sàn giao dịch tập trung, tức là dữ liệu cập nhật không kịp thời. Ví dụ, đôi khi có thể không tìm thấy đơn hàng khi truy vấn ngay sau khi đặt hàng. Người ta khuyến cáo rằng sau một số hoạt động nhất định (Sleep(n)) Đợi vài giây trước khi truy vấn lại.
Sau đây là ví dụ về việc sử dụng hàm Dial để tạo kết nối API Websocket và đăng ký dữ liệu sổ lệnh:
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) + "`")
}
}
Các tin nhắn được sử dụng phổ biến nhất trong giao dịch là tin nhắn lệnh, tin nhắn hủy lệnh và tin nhắn chuyển lệnh.
{
"@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ệnh giới hạn:
Trong hàm lệnh được đóng gói trên nền tảng FMZ, giá trị orderFlags được sử dụng cho lệnh giới hạn là:ORDER_FLAGS_LONG_TERM = 64 # 长期订单Theo giới hạn của giao thức DYDX v4, thời hạn hiệu lực của lệnh dài nhất được áp dụng là 90 ngày (tất cả các loại lệnh trên DYDX v4 đều có thời hạn hiệu lực).
Lệnh thị trường:
Trong hàm lệnh được đóng gói trên nền tảng FMZ, giá trị orderFlags được lệnh thị trường sử dụng là:ORDER_FLAGS_SHORT_TERM = 0 # 短期订单, theo khuyến nghị của giao thức DYDX v4:
// Recommend set to oracle price - 5% or lower for SELL, oracle price + 5% for BUY
Vì đây không phải là lệnh thị trường thực sự nên giá oracle được sử dụng, cộng hoặc trừ 5% trượt giá làm lệnh thị trường. Cài đặt thời hạn hiệu lực của lệnh ngắn hạn cũng khác với lệnh dài hạn. Lệnh ngắn hạn sử dụng thời hạn hiệu lực của chiều cao khối. Theo khuyến nghị của dydx v4, nó được đặt thành khối hiện tại + 10 chiều cao khối trước khi hết hạn.
Mã đơn hàng: Vì thao tác đặt hàng được thực hiện trực tiếp trên chuỗi, sẽ không có ID đơn hàng nào được tạo bởi trình lập chỉ mục sau khi tin nhắn được phát và thứ tự của trình lập chỉ mục không thể được sử dụng làm giá trị trả về của hàm đặt hàng nền tảng. Để đảm bảo tính duy nhất của ID đơn hàng và độ chính xác của truy vấn đơn hàng, đơn hàng lập chỉ mục được trả về. ID đơn hàng bao gồm các thông tin sau (phân tách bằng dấu phẩy):
Tóm tắt tin nhắn hủy đơn hàng
{
"@type": "/dydxprotocol.clob.MsgCancelOrder",
"orderId": {
"subaccountId": {
"owner": "xxx"
},
"clientId": 2585872024,
"orderFlags": 64,
"clobPairId": 1
},
"goodTilBlockTime": 1742295981
}
Cần phải truyền vào ID đơn hàng được trả về bởi giao diện đơn hàng của nền tảng FMZ.
{
"@type": "/dydxprotocol.sending.MsgCreateTransfer",
"transfer": {
"sender": {
"owner": "xxx"
},
"recipient": {
"owner": "xxx",
"number": 128
},
"amount": "10000000"
}
}
Nhiều tài khoản phụ có thể được tạo theo địa chỉ dydx v4 hiện tại. Tài khoản phụ có subAccountNumber 0 là tài khoản phụ đầu tiên được tạo tự động. ID tài khoản phụ có subAccountNumber lớn hơn hoặc bằng 128 được sử dụng cho giao dịch vị thế bị cô lập, yêu cầu ít nhất 20 tài sản USDC. Ví dụ, bạn có thể đi từ subAccountNumber 0 -> 128 hoặc từ subAccountNumber 128 -> 0. Việc chuyển nhượng đòi hỏi phải tiêu tốn Phí Gas. Gas Fee có thể sử dụng token USDC và dydx.
Nội dung trên giải thích vắn tắt một số chi tiết đóng gói. Tiếp theo, chúng ta hãy thực hành sử dụng cụ thể. Ở đây chúng tôi sử dụng mạng thử nghiệm dYdX v4 để trình diễn. Mạng thử nghiệm về cơ bản giống như mạng chính và có vòi tự động để nhận tài sản thử nghiệm . Người giám hộ triển khai Tôi sẽ không đi sâu vào chi tiết về hoạt động này và tạo một bài kiểm tra thực tế trên FMZ.
Sau khi kết nối thành công với Ứng dụng dYdX v4 bằng ví tiền điện tử (tôi sử dụng ví imToken ở đây), hãy yêu cầu tài sản thử nghiệm của bạn rồi xuất mã ghi nhớ cho tài khoản dYdX v4 hiện tại của bạn (lấy từ ví của bạn).

Cấu hình mnemonic trên nền tảng FMZ. Ở đây chúng tôi sử dụng phương pháp tệp cục bộ để cấu hình nó (bạn cũng có thể điền trực tiếp và cấu hình nó cho nền tảng. mnemonic được cấu hình sau khi mã hóa, không phải ở dạng văn bản thuần túy).

Đặt nó vào thư mục ID đĩa thực trong thư mục custodian. Tất nhiên, nó cũng có thể được đặt trong các thư mục khác (đường dẫn cụ thể cần được ghi trong quá trình cấu hình).
Điền vào hộp chỉnh sửa ghi nhớ:file:///mnemonic.txt, đường dẫn thực tế tương ứng là:托管者所在目录/logs/storage/594291。

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())
}
Đọc thông tin tài khoản mạng thử nghiệm:
{
"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
}
Không chuyển sang mạng thử nghiệm, đã thử nghiệm với mạng chính
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) + "`")
}

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

Trang ứng dụng dYdX v4:

Mạng thử nghiệm đặt trước hai lệnh, thử lấy các lệnh đang chờ xử lý và hủy các lệnh đó.
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) + "`")
}

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

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

Chuyển sang tài khoản phụ có subAccountNumber là 128 và dữ liệu trả về bởi GetAccount là:
{
"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
}
Có thể thấy rằng tài khoản phụ có số subAccountNumber 128 đã chuyển 20 USDC.
Theo thứ tự, lấy TxHash và kiểm tra phương pháp gọi IO nút REST
Làm thế nào để lấy TxHash của một lệnh? Đối tượng trao đổi dydx sẽ lưu trữ TxHash, có thể truy vấn bằng ID lệnh. Tuy nhiên, sau khi chiến lược dừng lại, bản đồ băm tx lệnh được lưu trong bộ nhớ đệm sẽ bị xóa.
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)
}
}

Tin nhắn được truy vấn thông qua TxHash:
var ret = exchange.IO(“api”, “GET”, “/cosmos/tx/v1beta1/txs/” + txHash)
Nội dung quá dài, sau đây là một số đoạn trích để minh họa:
{
"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": []
},
...
Các bài kiểm tra trên dựa trên người giám hộ mới nhất. Bạn cần tải xuống người giám hộ mới nhất để hỗ trợ dYdX v4 DEX
Cảm ơn các bạn đã ủng hộ và đọc bài viết.