Skip to content

Running XayaX

Andy Colosimo edited this page Jun 12, 2026 · 1 revision

Running XayaX

This page shows you how to run XayaX, the bridge that connects Xaya games to Polygon. By the end you will have a XayaX container running on your machine, serving the Xaya-Core-style JSON-RPC interface that every Game State Processor (GSP) consumes, and you will know how to verify it is synced, how its ZMQ notifications work, and how to keep its data across restarts.

What XayaX is

Xaya games don't talk to Polygon directly. They talk to XayaX, a translation daemon that subscribes to an EVM chain, watches the XayaAccounts contract for name registrations and moves, and re-exposes everything through the same JSON-RPC + ZMQ interface that the original Xaya Core daemon provided. A GSP built with libxayagame neither knows nor cares which chain is behind the bridge — Polygon, another EVM chain, or Xaya Core itself (see Other-Chains).

flowchart LR
    P[Polygon PoS<br/>XayaAccounts contract] -- "EVM JSON-RPC<br/>(contract events)" --> X[XayaX bridge<br/>eth connector]
    X -- "Xaya-Core-style JSON-RPC<br/>port 8000" --> G[GSP<br/>e.g. moverd]
    X -- "ZMQ block notifications<br/>tcp://xayax:28555" --> G
    G -- "Game-state JSON-RPC" --> C[Your tools / clients]
Loading

Data flows one way: chain → XayaX → GSP → clients. XayaX never writes to the chain; players send moves directly from their wallets. For the full picture, see Xaya-Architecture.

The Docker image

The Xaya team publishes a ready-to-run image, xaya/xayax. You don't need to build anything to run the bridge:

docker pull xaya/xayax

The image contains the xayax binary with its chain connectors. For Polygon (or any EVM chain) you use the eth connector; the core connector targets the original Xaya Core blockchain.

The invocation, flag by flag

This is the exact, verified command the tutorial's Docker setup runs:

xayax eth
  --eth_rpc_url=https://polygon-node.xaya.io
  --accounts_contract=0x8C12253F71091b9582908C8a44F78870Ec6F304F
  --port=8000
  --listen_locally=false
  --zmq_address=tcp://xayax:28555
  --logtostderr
Flag What it does
eth Selects the EVM connector. Use this for Polygon and any other EVM chain with a XayaAccounts deployment.
--eth_rpc_url The EVM node XayaX reads blocks from. https://polygon-node.xaya.io is a public Polygon RPC run by the Xaya team; you can substitute your own Polygon node or any RPC provider.
--accounts_contract The XayaAccounts (ERC-721 names) contract to watch. On Polygon mainnet this is 0x8C12253F71091b9582908C8a44F78870Ec6F304F.
--port=8000 Port for XayaX's own JSON-RPC server — the endpoint your GSP points its --xaya_rpc_url at.
--listen_locally=false Binds the RPC server on all interfaces inside the container instead of only 127.0.0.1. Required so other containers (your GSP) can reach it. Host exposure is still controlled by your Docker port mapping.
--zmq_address The ZMQ endpoint XayaX binds for block notifications and advertises to clients. See the warning below — this must be an address the GSP container can actually dial, so use the Docker service name (tcp://xayax:28555), never localhost.
--logtostderr Sends glog output to stderr so docker logs shows it.

The --zmq_address warning

GSPs do not get the ZMQ address from their own configuration — they ask XayaX for it (via getzmqnotifications) and then connect to whatever address XayaX advertises. That advertised address is exactly the value of --zmq_address. If you set it to tcp://localhost:28555, the GSP container will dutifully try to connect to its own localhost and never receive a block notification. With Docker, always use the XayaX container's service name, e.g. tcp://xayax:28555, and keep both containers on the same Docker network. A correctly connected GSP logs:

Detected ZMQ blocks endpoint: tcp://xayax:28555

Sync behavior

XayaX does not replay the whole chain. With a brand-new data volume it starts near the current Polygon tip and is serving RPC within about two minutes. Older blocks are backfilled on demand: when a GSP asks for history (for example a game whose genesis is at block 88365000 while the bridge started at tip ~88370000), XayaX fetches those blocks from the EVM node and serves them. You don't need to wait for any long initial sync before starting your GSP.

Checking that it works

The compose setup maps XayaX's RPC to 127.0.0.1:8101 on the host. Query it like a Xaya Core node:

curl -s -X POST -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"getblockchaininfo","params":[]}' \
  http://127.0.0.1:8101

You should see something like:

{"id":1,"jsonrpc":"2.0","result":{"bestblockhash":"...","blocks":88370214,"chain":"polygon"}}

Two things to check: "chain":"polygon" confirms you're bridging the right network, and "blocks" should track the live Polygon tip (compare with a block explorer; Polygon produces a block roughly every 2 seconds, so the number climbs fast). If the number keeps increasing on repeated calls, the bridge is healthy.

You can also watch the logs:

docker logs -f mover-xayax-1

(The container name depends on your compose project name.)

ZMQ reachability for GSP containers

The JSON-RPC port is only half the interface. XayaX pushes new-block notifications over ZMQ, and the GSP subscribes to them to learn about attached and detached blocks in real time. For this to work:

  • The GSP container and the XayaX container must be on the same Docker network, so the service name xayax resolves.
  • The advertised --zmq_address must use that resolvable name (see the warning above).
  • You do not need to publish the ZMQ port (28555) to the host unless a GSP runs outside Docker.

If you run XayaX on one machine and GSPs elsewhere, the same rule generalizes: --zmq_address must be an address the GSP host can reach over the network.

Running it: compose profile vs. standalone

Via the tutorial's compose profile (recommended)

The mover tutorial ships a docker-compose.yml (see Tutorial-Mover-Part-1-Setup) where XayaX is a service behind the xayax profile:

cd ~/mover-polygon/docker
docker compose --profile xayax up -d --build

This starts both XayaX and the moverd GSP on a shared network. If you already run a XayaX instance elsewhere, omit --profile xayax and point the GSP at it with XAYA_RPC_URL — remembering that the ZMQ addresses XayaX advertises must be reachable from the GSP container.

The relevant service definition looks like this:

  xayax:
    image: xaya/xayax
    profiles:
      - xayax
    restart: unless-stopped
    networks:
      - mover-net
    ports:
      - "127.0.0.1:${XAYAX_PORT:-8101}:8000"
    volumes:
      - xayax-data:/xayax
    command:
      - "eth"
      - "--eth_rpc_url=${ETH_RPC_URL:-https://polygon-node.xaya.io}"
      - "--accounts_contract=${ACCOUNTS_CONTRACT:-0x8C12253F71091b9582908C8a44F78870Ec6F304F}"
      - "--port=8000"
      - "--listen_locally=false"
      - "--zmq_address=tcp://xayax:28555"
      - "--logtostderr"

Note that the RPC port is published on 127.0.0.1 only — handy for local curl checks without exposing the bridge to your LAN. The tutorial's compose file also pins the Docker network subnet (172.16.0.0/24), because Docker's auto-assigned 192.168.0.0/20 range can shadow your host's 192.168.x LAN routes. If 172.16.0.0/24 collides with a network you actually use, pick a different private subnet — run ip route on the host to see which ranges are taken.

Standalone with docker run

One bridge can serve many GSPs, so you may prefer to run XayaX once, independently of any particular game:

docker network create xaya-net

docker run -d --name xayax \
  --network xaya-net \
  --restart unless-stopped \
  -p 127.0.0.1:8101:8000 \
  -v xayax-data:/xayax \
  xaya/xayax eth \
  --eth_rpc_url=https://polygon-node.xaya.io \
  --accounts_contract=0x8C12253F71091b9582908C8a44F78870Ec6F304F \
  --port=8000 \
  --listen_locally=false \
  --zmq_address=tcp://xayax:28555 \
  --logtostderr

The container name (--name xayax) must match the hostname in --zmq_address, and every GSP container you start must join the same network (--network xaya-net) with --xaya_rpc_url=http://xayax:8000.

Data persistence

XayaX keeps its state under /xayax inside the container, which both setups above mount as the named Docker volume xayax-data. With the volume in place, restarts pick up where the bridge left off instead of resyncing from the tip:

docker compose --profile xayax restart xayax   # state survives
docker volume rm mover_xayax-data              # only if you want a truly fresh start (compose project down first)

Losing the volume is not catastrophic — a fresh bridge is serving again within about two minutes and backfills history on demand — but keeping it avoids redundant work and keeps your GSPs' block source steady.

Next steps

Clone this wiki locally