Building an app using the WORM

This page goes over how you can develop an application that leverages outputs from the worms brain that have been stored and verified on-chain.

Worm outputs as well as other metadata are stored in logs within Hyperliquid Testnet. Transactions containing worm outputs will store left and right muscle movements which can be parsed and translated into physical or non-physical movements.

Querying the On-Chain Worm

The Hyperliquid Testnet can be queried like any other Ethereum based chain. To query for blocks on the chain that contain Worm logs you need the following:

  • hypeAPI = "https://api.hyperliquid-testnet.xyz/evm"

  • contractAddress = "<WORM Brain State Address>"

  • ABI

WORM Brain State Address can be found in the Contracts & IP Addresses section under the heading "WORM Brain State".

With the above you can use the the testnet RPC endpoint to query blocks and transactions that contain worm logs. For example using Go we can query blocks and logs like so:

// Connect to Hyperliquid or any Ethereum-compatible blockchain
client, err := ethclient.Dial(hypeAPI)
if err != nil {
	return nil, fmt.Errorf("error connecting to hype client: %w", err)
}

// ABI parsing
contractAbi, err := abi.JSON(strings.NewReader(abiStr))
if err != nil {
	return nil, fmt.Errorf("failed to parse contract ABI: %w", err)
}

query := ethereum.FilterQuery{
	FromBlock: big.NewInt(from),
	ToBlock:   big.NewInt(to),
	Addresses: []common.Address{contractAddress},
}

// Fetch logs
logs, err := bf.client.FilterLogs(ctx, query)
if err != nil {
	log.Fatalf("Failed to fetch logs: %v", err)
}

cds := make([]contractData, 0, len(logs))

// Decode logs
for _, vLog := range logs {
	event := struct {
		DeltaX            *big.Int
		DeltaY            *big.Int
		LeftMuscle        *big.Int
		RightMuscle       *big.Int
		PositionTimestamp *big.Int
		PositionPrice     *big.Int
	}{}

	if err := bf.abi.UnpackIntoInterface(&event, "WormStateUpdated", vLog.Data); err != nil {
		return nil, fmt.Errorf("failed to unpack log data: %w", err)
	}

	cd := contractData{
		transactionHash: vLog.TxHash.String(),
		block:           int(vLog.BlockNumber),
		leftMuscle:      event.LeftMuscle.Int64(),
		rightMuscle:     event.RightMuscle.Int64(),
		price:           float64(event.PositionPrice.Int64()) / 10000000,
		ts:              time.Unix(event.PositionTimestamp.Int64(), 0), // Set ts by converting the UNIX timestamp
	}

Once the values are parsed from the logs they can be utilized to influence whatever your application needs.

Storing State

It's recommended that if the worms left and right muscle movements are influencing some external entity or object that the state of the object and potentially it's history be stored. This will prevent the need to parse through the entire chains history across service restarts.

Last updated