O recurso está a ser carregado... Carregamento...

Prática quantitativa das bolsas DEX (1) -- dYdX v4 Guia do utilizador

Autora:FMZ~Lydia, Criado: 2024-12-26 15:32:24, Atualizado: 2025-01-14 11:22:18

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

Prefácio

Com a rápida ascensão das bolsas descentralizadas (DEX) no campo da negociação de criptomoedas, os comerciantes quantitativos viraram-se gradualmente para essas plataformas para uma negociação automatizada eficiente.

Este artigo introduz como praticar negociação quantitativa no dYdX v4, incluindo como usar sua API para negociar, obter dados de mercado e gerenciar contas.

  • Alteração do ambiente de ensaio
  • Consultas de informações de mercado
  • Informações de encomenda e consulta de informações de posição
  • Faça uma encomenda.
  • Gestão de subcontas
  • Pedido de método de nó

DYdX v4 DEX

  • Página de aplicação da testnet dYdX

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

  • ComodYdX v3Com o Ethereum, a negociação gera recompensas, que são recompensasdYdX tokens.

Conexão de carteira, login e informações de configuração

O exchange DEX anterior do protocolo dYdX v3 estava offline. O endereço atual do aplicativo dYdX v4 é:

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

Depois de abrir a página da App, há um botão para se conectar à carteira no canto superior direito.

Se você quiser testar e familiarizar-se com o ambiente da rede de teste primeiro, você pode usar a rede de teste:

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

Além disso, clique no botão conectar carteira no canto superior direito, digitalize o código para conectar a carteira e verifique a assinatura. Depois que a carteira for conectada com sucesso, um endereço dydx v4 será gerado automaticamente. Esse endereço será exibido no canto superior direito da página do aplicativo. Clique nele e um menu aparecerá. Existem operações como recarga, retirada e transferência. Uma das diferenças entre a rede principal dYdX (ambiente de produção) e a rede de teste é que, quando você clica em recarga na rede de teste, 300 ativos USDC serão cobrados automaticamente usando a torneira para teste. Se você quiser fazer transações reais na dYdX, precisa cobrar ativos USDC. A recarga também é muito conveniente e compatível com vários ativos e cadeias para recarga.

  • Endereço da conta dYdX v4 O endereço da conta dYdX v4 é derivado do endereço da carteira.dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx, que é um endereço que começa com dydx1.

  • Mnemônica Você pode usar o botão Export Password no menu no canto superior direito para exportar as mnemônicas da conta de endereço dYdX atual. Ao adicionar uma troca na plataforma FMZ, você precisa configurar essa mnemônica.

Os mnemônicos podem ser configurados diretamente na plataforma FMZ ou salvos localmente no docker.

Diferenças entre Mainnet e Testnet

O ambiente da testnet difere do ambiente da mainnet em alguns aspectos.

  • Transferência de activos para uma subconta. A rede principal tem um mecanismo de limpeza de sub-contas.subAccountNumber >= 128, se a subconta do ID não tiver posições, os activos serão automaticamente transferidos para a subconta cujo subconta-número seja 0. Durante o ensaio, verificou-se que a rede de ensaio não possui este mecanismo (ou as condições de activação são diferentes e não foi activada na rede de ensaio).
  • Alguns nomes simbólicos. O token nativo dydx tem nomes diferentes: mainnetDYDX, rede de ensaioDv4TNT
  • Configuração de endereço, como ID da cadeia, endereço do nó, endereço do indexador, etc. Há muitos nós e configurações, aqui está um deles:

Rede principal: Endereço do indexador:https://indexer.dydx.tradeIdentificador da cadeia:dydx-mainnet-1Nodo REST:https://dydx-dao-api.polkachu.com:443

Rede de teste: Endereço do indexador:https://indexer.v4testnet.dydx.exchangeIdentificador da cadeia:dydx-testnet-4Nodo REST:https://dydx-testnet-api.polkachu.com

Arquitetura de protocolo dYdX v4

O protocolo dYdX v4 é desenvolvido com base no ecossistema cosmos.

  • Um indexador responsável pela consulta de informações do ticker, informações da conta, etc.
  • mensagens de pedido dydx blockchain, mensagens de cancelamento de pedido, mensagens de transferência, etc.

Indicador

O serviço de indexação fornece protocolos REST e Websocket.

  • Protocolo REST A interface do protocolo REST suporta consulta de informações de mercado, informações de conta, informações de posição, informações de ordem e outras consultas, e foi encapsulada como uma interface API unificada na plataforma FMZ.

  • Protocolo WebSocket Na plataforma FMZ, você pode usar a função Dial para criar uma conexão Websocket e se inscrever em informações de mercado.

Deve-se notar que o indexador do dydx v4 tem o mesmo problema que as trocas centralizadas, ou seja, as atualizações de dados não são tão oportunas. Por exemplo, às vezes você pode não ser capaz de encontrar a ordem se você consultá-la imediatamente após a colocação de um pedido.Sleep(n)) certas operações antes da consulta.

Aqui está um exemplo de como usar a função Dial para criar uma conexão Websocket API e assinar dados do livro de pedidos:

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

Transmissão de mensagem de nó da cadeia dYdX

As mensagens mais usadas em transações são mensagens de encomenda, mensagens de cancelamento de encomenda e mensagens de transferência.

  • Resumo da mensagem de ordem
{
  "@type": "/dydxprotocol.clob.MsgPlaceOrder",
  "order": {
    "orderId": {
      "subaccountId": {
        "owner": "xxx"
      },
      "clientId": xxx,
      "orderFlags": 64,
      "clobPairId": 1
    },
    "side": "SIDE_BUY",
    "quantums": "2000000",
    "subticks": "3500000000",
    "goodTilBlockTime": 1742295981
  }
}
  • Ordem limite: Na função de ordens encapsulada na plataforma FMZ, o valor de orderFlags utilizado para ordens limite é:ORDER_FLAGS_LONG_TERM = 64 # Long-term orderDe acordo com as limitações do protocolo dydx v4, é utilizado o período de validade da encomenda mais longo, que é de 90 dias (todos os tipos de encomendas no dydx v4 têm períodos de validade).

  • Ordem de mercado: Na função de ordens encapsulada na plataforma FMZ, o valor do orderFlags utilizado para ordens de mercado é:ORDER_FLAGS_SHORT_TERM = 0 # Short-term order, de acordo com as recomendações do protocolo dydx v4:

// Recomendação definida para o preço do oráculo - 5% ou menos para VENDER, preço do oráculo + 5% para COMPRAR

Como não é uma ordem de mercado verdadeira, o preço do oráculo é usado, mais ou menos 5% de deslizamento como a ordem de mercado. O período de validade das ordens de curto prazo também é diferente do de ordens de longo prazo. As ordens de curto prazo usam o período de validade de altura do bloco, que é definido para o bloco atual + 10 alturas do bloco de acordo com a recomendação do dydx v4.

  • ID da encomenda: Uma vez que a operação de ordem é executada diretamente na cadeia, não haverá ID de ordem gerada pelo indexador após a transmissão da mensagem, e a ordem de indexador não pode ser usada como o valor de retorno da função de ordem da plataforma.

Pares de negociação Endereço da conta corrente dydx Número da subconta (subcontaNumero) ClientId (gerado aleatoriamente) clobPairId (ID do símbolo da transacção) ordem goodTilData (milissegundos)

  • Resumo da mensagem de cancelamento da encomenda
{
  "@type": "/dydxprotocol.clob.MsgCancelOrder",
  "orderId": {
    "subaccountId": {
      "owner": "xxx"
    },
    "clientId": 2585872024,
    "orderFlags": 64,
    "clobPairId": 1
  },
  "goodTilBlockTime": 1742295981
}

O ID de encomenda devolvido pela interface de encomenda da plataforma FMZ deve ser transmitido.

  • Resumo da mensagem de transferência
{
  "@type": "/dydxprotocol.sending.MsgCreateTransfer",
  "transfer": {
    "sender": {
      "owner": "xxx"
    },
    "recipient": {
      "owner": "xxx",
      "number": 128
    },
    "amount": "10000000"
  }
}

Muitas sub-contas podem ser criadas sob o endereço dydx v4 atual. A sub-conta com subAccountNumber 0 é a primeira sub-conta criada automaticamente. O ID da sub-conta com subAccountNumber maior ou igual a 128 é usado para negociação de posição isolada, que requer pelo menos 20 ativos USDC. Por exemplo, você pode ir do subAccountNumber 0 -> 128, ou do subAccountNumber 128 -> 0. As transferências exigem taxa de gás.

FMZ Plataforma dYdX v4 Prática

O conteúdo acima explica brevemente alguns detalhes de embalagem. Em seguida, vamos praticar o uso específico. Aqui usamos a rede de teste dYdX v4 para demonstração. A rede de teste é basicamente a mesma que a rede principal, e há uma torneira automática para receber ativos de teste. A operação de implantação do docker não será repetida. Crie um teste de negociação ao vivo no FMZ.

1. Configuração

Depois de se conectar ao aplicativo dYdX v4 com sucesso usando uma carteira de criptomoeda (eu uso a carteira imToken aqui), reivindique seus ativos de teste e, em seguida, exporte o mnemônico para sua conta atual dYdX v4 (derivada de sua carteira).

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

Configure o mnemônico na plataforma FMZ. Aqui usamos o método de arquivo local para configurá-lo (você também pode preenchê-lo diretamente e configurá-lo para a plataforma. O mnemônico é configurado após criptografia, não em texto simples).

  • Arquivo mnemónico: mnemónico.txt

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

Coloque-o no diretório de pasta do ID de negociação ao vivo, sob o diretório do docker.

  • Configure o intercâmbio no FMZ

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

Preencha a caixa de edição mnemônica:file:///mnemonic.txt, o caminho real correspondente é:docker directory/logs/storage/594291.

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

2. Mudar para a rede de teste 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()) 
}

Leia as informações da conta da rede de teste:

{
	"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. Inquérito de informações de mercado

Não trocou para a rede de ensaio, testado com a rede principal

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

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

4. Faça um pedido

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

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

Página do aplicativo dYdX v4:

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

5. Informações sobre a encomenda

A rede de ensaios realiza duas encomendas com antecedência, verifica as encomendas pendentes e cancela as encomendas.

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

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

6. Pergunta de informação de posição

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

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

7. Gestão de subcontas

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

Informações do registo:

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

Troque para a subconta cujo subAccountNumber é 128, e os dados devolvidos pelo GetAccount são:

{
	"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
}

Pode-se ver que a sub-conta com a subconta número 128 transferiu 20 USDC.

8. Obter TxHash e chamar a interface do nó REST

De acordo com a ordem, obter TxHash e testar o método de IO chamando REST nó

Como obter o TxHash de uma ordem? O objeto de troca dydx armazenará o TxHash em cache, que pode ser consultado usando o ID da ordem. No entanto, depois que a estratégia for parada, o mapa de hash da ordem tx em cache será limpo.

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

Quantitative Practice of DEX Exchanges (1) – dYdX v4 User Guide

Mensagens consultadas através do TxHash:

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

O conteúdo é muito longo, por isso aqui estão alguns trechos para demonstração:

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

O fim

Os testes acima são baseados no mais recente docker. Você precisa baixar o mais recente docker para suportar dYdX v4 DEX

Obrigado pelo apoio e por ler.


Mais.