리소스 로딩... 로딩...

DEX 거래소 정량화 연습 ((1)-- dYdX v4 사용 설명서

저자:발명가들의 수량화 - 작은 꿈, 창작: 2024-12-24 17:09:32, 업데이트: 2024-12-26 21:41:46

[TOC]

img

전문

분산 거래소 (DEX) 가 암호화폐 거래 분야에서 급격히 상승함에 따라, 양자 거래자는 효율적인 자동화 거래를 위해 점차 이러한 플랫폼으로 전환하기 시작했습니다. dYdX는 가장 인기있는 분산 거래 플랫폼 중 하나로서 강력한 거래 기능을 제공하며 미래 상영 계약 거래를 지원합니다. 최신 버전 v4는 성능과 사용자 경험을 최적화하여 많은 양자 거래자의 선호도가 높습니다.

이 문서는 dYdX v4에서 거래의 API를 사용하여 거래, 시장 데이터를 확보하고 계정을 관리하는 것을 포함하여 거래 관행을 양산하는 방법에 대해 설명합니다.

  • 테스트 환경 전환
  • 시장 정보 검색
  • 주문 정보, 보관 정보 문의
  • 아래의 거래
  • 계정 관리
  • 노드 메소드 요청

dYdX v4 DEX

  • dYdX 테스트 웹 앱 페이지

    img

  • 그리고dYdX v3또한, 거래는 보상, 보상으로 이어집니다.dYdX토큰.

    img

지갑 연결, 로그인, 설정 정보

이전 dYdX v3 프로토콜의 DEX 거래소는 종료되었으며 현재 dYdX v4 앱 주소는:

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

앱 페이지에 접속하면 오른쪽 상단에는 연결 지갑 버튼이 있습니다.

테스트 네트워크 환경 테스트에 익숙해지고 싶다면 테스트 네트워크를 사용하십시오.

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

또한 오른쪽 상단에 있는 연결 지갑 버튼을 클릭하고, 스캔 코드 연결 지갑, 서명 확인. 지갑 연결이 성공한 후에는 자동으로 dydx v4 주소를 생성하고, 앱 페이지의 오른쪽 상단에 있는 이 주소를 표시하고, 클릭하면 메뉴가 튀어나옵니다. 여기에는 충전, 인화, 송금 등의 동작이 있습니다. dYdX 주식 네트워크 (제조 환경) 와 테스트 네트워크의 차이점 중 하나는: 테스트 네트워크에서 클릭 충전, 자동으로 300 USDC 자산을 충전하는 탭을 사용하여 테스트합니다.

  • dYdX v4 계정 주소 dYdX v4 계정 주소는 지갑 주소에서 파생되었으며, dYdX v4 계정 주소는 다음과 같습니다.dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx,는 dydx1의 시작 주소이다. 이 주소는 블록체인 익스플로러에서 검색할 수 있다.

  • 도움말 오른쪽 상단 메뉴에서 "패스워드 수출" 버튼을 클릭하여 현재 dYdX 주소 계정의 서스워드를 수출할 수 있습니다. FMZ 플랫폼에 거래소를 추가할 때 서스워드를 구성해야 합니다.

    보조말은 FMZ 플랫폼에서 직접 구성할 수 있고, 또한 관리자가 로컬로 저장할 수 있으며, dydx v4 거래소 객체를 사용할 때, 기록 보조말의 파일 내용을 읽을 수 있으며, 이 문서의 실제 동작 부분에서 시범화 될 것입니다.

홈 네트워크, 테스트 네트워크의 차이

테스트 네트워크 환경은 기본 네트워크 환경과 몇 가지 측면에서 차이가 있습니다.

  • 자금의 분배와 자금의 분배 이 사이트의 주요 사이트에는 계정 청소 장치가 있습니다.subAccountNumber >= 128이 ID의 계정 계정이 보관되지 않은 경우 자산을 자동으로 0 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계정 계 테스트에서는 테스트 네트워크가 이러한 메커니즘을 가지고 있지 않다는 것을 발견했습니다 (또는 다른 트리거 조건이 테스트 네트워크에서 트리거되지 않았습니다).
  • 일부 토큰 이름. 원본 도큰 dydx의 다른 이름: 메인 웹DYDX테스트 네트워크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 프로토콜은 코스모스 생태계 개발에 기반하고 있으며, dYdX v4 DEX 시스템 거래 관련 내용은 크게 2개의 부분으로 구성되어 있습니다.

  • 시장 정보, 계좌 정보 등의 검색을 담당하는 인덱스.
  • dydx 블록체인 주문 메시지, 철회 메시지, 송금 메시지 등.

인덱스

인덱서비스는 REST 프로토콜과 웹소켓 프로토콜을 제공합니다.

  • REST 프로토콜 REST 프로토콜 인터페이스는 시장 정보, 계정 정보, 보유 정보, 주문 정보와 같은 쿼리를 지원하며 FMZ 플랫폼에는 플랫폼 통일 API 인터페이스로 포장되어 있습니다.

  • 웹소켓 프로토콜 FMZ 플랫폼에서는 Dial 기능을 사용하여 웹소켓 연결, 구독 시장 등의 정보를 만들 수 있습니다.

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 프로토콜의 제안에 따라:

      // 오라클 가격에 추천 설정 - 5% 또는 판매를 위해 낮은, 오라클 가격 + 5% 구매

      실제 시가 목록이 아니기 때문에, 예측기 가격과 5% 미만의 슬라이드 가격을 시가 목록으로 사용한다. 단기 주문의 유효기간 설정은 또한 장기 주문과 다르며, 단기 주문은 블록 높이의 유효기간을 사용하며, dydx v4의 추천에 따라 현재 블록 + 10 블록 높이에 설정된 후 유효하지 않는다.

    • 주문 ID: 하위 주문 작업은 문자열에서 직접 수행되기 때문에 메시지 방송 후 인덱서 생성된 주문 ID가 없으며, 인덱서 주문을 플랫폼 하위 주문 함수의 반환 값으로 사용할 수 없습니다.

      • 거래
      • dydx의 현재 계정 주소
      • 하위 계정 번호
      • 클라이언트 아이디 (randomly generated)
      • 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 주소로 많은 계정을 만들 수 있으며, subAccountNumber는 0으로 자동으로 생성되는 첫 번째 계정이며, subAccountNumber는 128에 해당하는 계정 ID보다 높으며, 20USD의 자산을 최소로 필요로합니다. 예를 들어, 서브 계정 번호 0 -> 128에서 또는 서브 계정 번호 128 -> 0에서 이동할 수 있습니다. 이동은 가스 요금을 소비해야합니다. 가스 요금은 USDC, dydx 토큰을 사용할 수 있습니다.

FMZ 플랫폼 dYdX v4 실습

위의 내용은 간단하게 몇 가지 패키지 세부 사항을 설명합니다. 다음으로 우리는 함께 구체적인 사용을 연습 할 것입니다. 여기 dYdX v4의 테스트 네트워크를 사용하여 테스트를 보여줍니다. 테스트 네트워크는 메인 네트워크와 기본적으로 일치하며 자동 펌프가 테스트 자산을 가져갈 수 있으며, 호스트 배포 작업은 더 이상 설명되지 않습니다. FMZ에서 실제 테스트를 만듭니다.

1, 구성

암호화폐 지갑으로 dYdX v4 앱을 성공적으로 연결한 후 (이곳에서 사용하는 imToken 지갑), 테스트 자산을 받아 현재 dYdX v4 계정 (지갑에서 파생된) 을 출력합니다.

img

구독어를 FMZ 플랫폼에서 구성합니다. 여기서 우리는 로컬 파일 방식으로 구성합니다. (또한 직접 작성하여 플랫폼에 구성할 수도 있습니다. 구독어는 비공개 문자가 아니라 암호화된 설정에 있습니다.)

  • 助记词文件:mnemonic.txt

    img

    호스트 디렉토리 아래의 디스크 ID 폴더 디렉토리에 넣고, 물론 다른 디렉토리에도 넣을 수 있습니다.

  • FMZ에서 거래소를 구성합니다.

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

    이 문서는 다른 문장과 다른 문장들을 포함하고 있습니다.file:///mnemonic.txt이 모든 것은 우리가 할 수 있는 일입니다.托管者所在目录/logs/storage/594291

    img

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

img

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

img

dYdX v4 앱 페이지:

img

5. 주문 정보

테스트 네트워크는 두 개의 주문을 미리 올리고, 테스트는 현재 주문을 얻고 주문을 취소합니다.

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

img

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

img

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

img

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
}

자, 자, 자, 자, 자, 자, 자, 자, 자.

8, TxHash를 열고 REST 노드 인터페이스를 호출합니다.

주문에 따라 TxHash를 획득하고 IO가 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)
    }
}

img

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를 지원합니다.

이 글을 읽은 모든 분들께 감사드립니다.


더 많은