En la carga de los recursos... Cargando...

Práctica cuantitativa de los intercambios DEX (1) -- Guía de usuario de dYdX v4

El autor:FMZ~Lydia, Creado: 2024-12-26 15:32:24, Actualizado: 2024-12-26 17:36:31

Prefacio

Con el rápido aumento de los intercambios descentralizados (DEX) en el campo del comercio de criptomonedas, los comerciantes cuantitativos se han vuelto gradualmente a estas plataformas para un comercio automatizado eficiente. Como una de las plataformas de comercio descentralizado más populares, dYdX proporciona funciones comerciales potentes y admite el comercio de contratos perpetuos de futuros.

Este artículo presentará cómo practicar el comercio cuantitativo en dYdX v4, incluida la forma de usar su API para operar, obtener datos de mercado y administrar cuentas.

  • Cambio de entorno de ensayo
  • Consulta de información sobre el mercado
  • Información de pedido y consulta de información de posición
  • Haga un pedido.
  • Gestión de subcuentas
  • Solicitud de método de nodo

DYdX v4 DEX

  • Página de aplicación de la red de pruebas dYdX

img

  • ComodYdX v3Con Ethereum, el comercio genera recompensas, que son recompensasdYdX tokens.

Conexión, inicio de sesión e información de configuración de la billetera

El anterior intercambio DEX del protocolo dYdX v3 ha estado fuera de línea.

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

Después de abrir la página de la aplicación, hay un botón para conectarse a la billetera en la esquina superior derecha.

Si desea probar y familiarizarse con el entorno de la red de prueba primero, puede usar la red de prueba:

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

Además, haga clic en el botón de conexión de la billetera en la esquina superior derecha, escanee el código para conectar la billetera y verifique la firma. Después de que la billetera se conecte con éxito, se generará automáticamente una dirección dydx v4. Esta dirección se mostrará en la esquina superior derecha de la página de la aplicación. Haga clic en ella y aparecerá un menú. Hay operaciones como recargar, retirar y transferir. Una de las diferencias entre la red principal dYdX (entorno de producción) y la red de prueba es que cuando hace clic en recargar en la red de prueba, se cargarán automáticamente 300 activos USDC utilizando el grifo para la prueba. Si desea realizar transacciones reales en dYdX, debe cargar activos USDC. Recargar también es muy conveniente y compatible con múltiples activos y cadenas para recargar.

  • Dirección de la cuenta dYdX v4 La dirección de la cuenta dYdX v4 se deriva de la dirección de la billetera.dydx1xxxxxxxxxxxxxxxxxxxxq2ge5jr4nzfeljxxxx, que es una dirección que comienza con dydx1. Esta dirección se puede consultar en exploradores de blockchain.

  • Mnemónicos Puede utilizar el botón Export Password en el menú de la esquina superior derecha para exportar las mnemónicas de la cuenta de dirección dYdX actual.

Los mnemónicos se pueden configurar directamente en la plataforma FMZ o guardar localmente en el docker.

Diferencias entre Mainnet y Testnet

El entorno de testnet es diferente del entorno de mainnet en algunos aspectos.

  • Transferencia de activos a una subcuenta. La red principal tiene un mecanismo de limpieza de subcuentas.subAccountNumber >= 128, si la subcuenta del ID no tiene posiciones, los activos se limpiarán automáticamente en la subcuenta cuyo subcuenta Número es 0. Durante los ensayos, se comprobó que la red de ensayo no tiene este mecanismo (o las condiciones de activación son diferentes y no se ha activado en la red de ensayo).
  • Ciertos nombres simbólicos. El token nativo dydx tiene diferentes nombres: mainnetDYDX, red de pruebasDv4TNT
  • Configuración de direcciones, como el identificador de cadena, la dirección del nodo, la dirección del índice, etc. Hay muchos nodos y configuraciones, aquí está uno de ellos:

La red principal: Dirección del indexador:https://indexer.dydx.tradeIdentificador de la cadena:dydx-mainnet-1Nodo REST:https://dydx-dao-api.polkachu.com:443

Redes de prueba: Dirección del indexador:https://indexer.v4testnet.dydx.exchangeIdentificador de la cadena:dydx-testnet-4Nodo REST:https://dydx-testnet-api.polkachu.com

Arquitectura del protocolo dYdX v4

El protocolo dYdX v4 se desarrolla basado en el ecosistema cosmos.

  • Un indexador responsable de consultar la información del ticker, la información de la cuenta, etc.
  • mensajes de pedido dydx blockchain, mensajes de cancelación de pedido, mensajes de transferencia, etc.

Indicador

El servicio de indexación proporciona protocolos REST y Websocket.

  • Protocolo REST La interfaz del protocolo REST admite consulta de información de mercado, información de cuenta, información de posición, información de pedido y otras consultas, y se ha encapsulado como una interfaz API unificada en la plataforma FMZ.

  • Protocolo WebSocket En la plataforma FMZ, puede usar la función Dial para crear una conexión Websocket y suscribirse a la información del mercado.

Se debe tener en cuenta que el índice de dydx v4 tiene el mismo problema que los intercambios centralizados, es decir, las actualizaciones de datos no son tan oportunas. Por ejemplo, a veces puede que no pueda encontrar el pedido si lo consulta inmediatamente después de realizar un pedido. Se recomienda esperar unos segundos después (Sleep(n)) ciertas operaciones antes de realizar la consulta.

Aquí hay un ejemplo de cómo usar la función Dial para crear una conexión Websocket API y suscribirse a los datos del libro 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) + "`")
    }
}

Difusión de mensajes de nodo de cadena dYdX

Los mensajes más utilizados en las transacciones son los mensajes de pedido, los mensajes de cancelación de pedido y los mensajes de transferencia.

  • Resumen del mensaje de orden
{
  "@type": "/dydxprotocol.clob.MsgPlaceOrder",
  "order": {
    "orderId": {
      "subaccountId": {
        "owner": "xxx"
      },
      "clientId": xxx,
      "orderFlags": 64,
      "clobPairId": 1
    },
    "side": "SIDE_BUY",
    "quantums": "2000000",
    "subticks": "3500000000",
    "goodTilBlockTime": 1742295981
  }
}
  • Orden límite: En la función de orden encapsulada en la plataforma FMZ, el valor de orderFlags utilizado para las órdenes límite es:ORDER_FLAGS_LONG_TERM = 64 # Long-term orderDe acuerdo con las limitaciones del protocolo dydx v4, se utiliza el período de validez del pedido más largo, que es de 90 días (todos los tipos de pedidos en dydx v4 tienen períodos de validez).

  • Orden del mercado: En la función de orden encapsulada en la plataforma FMZ, el valor de orderFlags utilizado para las órdenes de mercado es:ORDER_FLAGS_SHORT_TERM = 0 # Short-term order, de acuerdo con las recomendaciones del protocolo dydx v4:

// Recomendar el precio del oráculo - 5% o menos para vender, precio del oráculo + 5% para comprar

Como no es una orden de mercado verdadera, se utiliza el precio del oráculo, más o menos 5% de deslizamiento como la orden de mercado. El período de validez de las órdenes a corto plazo también es diferente al de las órdenes a largo plazo. Las órdenes a corto plazo utilizan el período de validez de la altura del bloque, que se establece en el bloque actual + 10 alturas del bloque de acuerdo con la recomendación de dydx v4.

  • Identificador del pedido: Dado que la operación de orden se realiza directamente en la cadena, no habrá ID de orden generado por el indexador después de que se transmita el mensaje, y la orden de indexador no se puede usar como el valor de retorno de la función de orden de la plataforma.

Pares de negociación Dirección de la cuenta corriente dydx Número de subcuenta (subcuenta Número) clienteId (generado al azar) clobPairId (ID del símbolo de la transacción) Orden Banderas goodTilData (millisegundos)

  • Resumen del mensaje de cancelación del pedido
{
  "@type": "/dydxprotocol.clob.MsgCancelOrder",
  "orderId": {
    "subaccountId": {
      "owner": "xxx"
    },
    "clientId": 2585872024,
    "orderFlags": 64,
    "clobPairId": 1
  },
  "goodTilBlockTime": 1742295981
}

El ID de pedido devuelto por la interfaz de pedido de la plataforma FMZ debe enviarse.

  • Resumen del mensaje de transferencia
{
  "@type": "/dydxprotocol.sending.MsgCreateTransfer",
  "transfer": {
    "sender": {
      "owner": "xxx"
    },
    "recipient": {
      "owner": "xxx",
      "number": 128
    },
    "amount": "10000000"
  }
}

Muchas subcuentas se pueden crear bajo la dirección dydx v4 actual. La subcuenta con subCuenta Número 0 es la primera subcuenta creada automáticamente. Por ejemplo, puede ir desde el subCuento Número 0 -> 128, o desde el subCuento Número 128 -> 0. Las transferencias requieren una tarifa de gas.

La plataforma FMZ dYdX v4 práctica

El contenido anterior explica brevemente algunos detalles del empaquetado. A continuación, practicemos el uso específico. Aquí usamos la red de prueba dYdX v4 para la demostración. La red de prueba es básicamente la misma que la red principal, y hay un grifo automático para recibir activos de prueba. La operación de implementación del docker no se repetirá.

1. Configuración

Después de conectarse con éxito a la aplicación dYdX v4 utilizando una billetera de criptomonedas (uso la billetera imToken aquí), reclame sus activos de prueba y luego exporte el mnemónico para su cuenta actual de dYdX v4 (derivada de su billetera).

img

Configurar el mnemónico en la plataforma FMZ. Aquí usamos el método de archivo local para configurarlo (también puede rellenarlo directamente y configurarlo en la plataforma. El mnemónico se configura después del cifrado, no en texto plano).

  • Archivo mnemónico: mnemónico.txt

img

Por supuesto, también se puede colocar en otros directorios (la ruta específica debe escribirse durante la configuración).

  • Configurar el intercambio en FMZ

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

Rellene el cuadro de edición mnemónica:file:///mnemonic.txt, la trayectoria real correspondiente es:docker directory/logs/storage/594291.

img

2. Cambiar a red de prueba 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()) 
}

Lea la información de la cuenta de la red de prueba:

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

Encuesta de información sobre el mercado

No cambió a la red de ensayo, probado con la red 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) +  "`")
}

img

4. Ponga una orden

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

img

Página de la aplicación dYdX v4:

img

5. Información sobre el pedido

La red de pruebas realiza dos pedidos por adelantado, prueba la obtención de los pedidos pendientes actuales y cancela los pedidos.

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

img

6. Consultas de información sobre la posición

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

img

7. Gestión de subcuentas

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

Información del registro:

img

Cambiar a la subcuenta cuyo subAccountNumber es 128, y los datos devueltos por GetAccount es:

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

Se puede ver que la subcuenta con la subcuenta número 128 ha transferido 20 USDC.

8. Obtener TxHash y llamar a la interfaz de nodo REST

De acuerdo con la orden, obtener TxHash y probar el método de IO llamando nodo REST

¿Cómo obtener el TxHash de una orden? El objeto de intercambio dydx almacenará en caché el TxHash, que se puede consultar utilizando el ID de orden. Sin embargo, después de que se detenga la estrategia, se borrará el mapa de hash de orden tx almacenado en caché.

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

img

Mensajes consultados a través de TxHash:

el valor de lasexchange.IO("api", GET, /cosmos/tx/v1beta1/txs/ + txHash)

El contenido es demasiado largo, así que aquí hay algunos extractos para demostrar:

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

El fin

Las pruebas anteriores se basan en el docker más reciente.

Gracias por su apoyo y gracias por leer.


Más.