MarketsModelsChatAPIDocs+ Create

Space Cat

POLOBonding curve0x97dda0…8aed80· 1h ago

Market cap

$4.3K

Price

$0.0₅427

24h volume

$216.79

9 trades

A little cat. A big dream. To the Mars... and beyond.

twitterwebsite

GPT-6 Astra

openai/gpt-6-astra

$8.27

compute

I can help build a 3D browser game with Robinhood blockchain integration, but I need to confirm what you mean by “Robinhood mainnet.” Please share the network’s official documentation or its RPC URL and chain ID—I can’t verify the intended network from your message alone.

If you don’t have a game concept yet, I suggest:

  • Gameplay: A 3D obstacle course with collectibles and timed runs.
  • Technology: Three.js for graphics, with mobile and keyboard controls.
  • Blockchain: Optional wallet connection and on-chain achievement badges.
  • Hosting: The game runs on a website; blockchain contracts handle achievements or ownership.

We should test the contracts before deploying to a live network. Don’t share private keys or seed phrases.

Is that the game you want, and can you link the Robinhood network documentation?

CREATE A 3D GAME ON ROBINHOOD MAINNET
chain ID 4663,URL robinhood-mainnet.infura.io

Here’s a playable Space Cat 3D browser game configured for chain ID 4663.

  • Fly with WASD or arrow keys and collect glowing orbs.
  • Play free; optionally save your score in an on-chain transaction using your wallet.
  • Saving requires gas and wallet approval. Scores are self-reported—not cheat-proof or tied to rewards.

I can provide the code, but I can’t deploy it from this chat or independently verify that your endpoint is mainnet. Your RPC may require an Infura API key: https://robinhood-mainnet.infura.io/v3/YOUR_KEY. Configure the network in your wallet using verified network details.

Save this as index.html and serve it using a static website host or local web server:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Space Cat 3D</title>
<style>
  * { box-sizing: border-box; }
  body {
    margin: 0; overflow: hidden; background: #060918;
    color: white; font: 15px system-ui;
  }
  canvas { display: block; }
  #hud {
    position: absolute; top: 16px; left: 16px;
    width: min(370px, calc(100vw - 32px));
    background: #10182ddd; padding: 18px; border-radius: 18px;
  }
  h1 { margin: 0 0 8px; font-size: 24px; }
  p { margin: 8px 0; }
  button {
    border: 0; border-radius: 10px; padding: 11px 15px;
    background: #b5ff53; color: #102000; font-weight: bold;
    cursor: pointer; margin: 4px 3px 4px 0;
  }
  button:disabled { opacity: .45; cursor: default; }
  #status { font-size: 12px; overflow-wrap: anywhere; color: #b9c8e7; }
  #pad {
    position: absolute; bottom: 20px; right: 20px;
    display: grid; grid-template-columns: repeat(3, 52px);
    gap: 5px; touch-action: none;
  }
  #pad button { margin: 0; background: #ffffffcc; font-size: 20px; }
</style>
</head>
<body>
<section id="hud">
  <h1>🚀 Space Cat 3D</h1>
  <p>Collect the orbs! WASD / arrows / touch controls.</p>
  <p>Score: <b id="score">0</b> · Time: <b id="time">30</b>s</p>
  <button id="start">Start game</button>
  <button id="connect">Connect wallet</button>
  <button id="save" disabled>Save score on-chain</button>
  <p id="status">Free to play. Saving a score costs network gas.</p>
</section>

<div id="pad">
  <span></span><button data-key="arrowup">↑</button><span></span>
  <button data-key="arrowleft">←</button>
  <button data-key="arrowdown">↓</button>
  <button data-key="arrowright">→</button>
</div>

<script type="module">
import * as THREE from
  "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js";

const CHAIN_ID = "0x1237"; // 4663
const $ = id => document.getElementById(id);
const status = text => $("status").textContent = text;

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x060918);

const camera = new THREE.PerspectiveCamera(
  55, innerWidth / innerHeight, 0.1, 150
);
camera.position.set(0, 24, 25);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

scene.add(new THREE.HemisphereLight(0xb9dfff, 0x222244, 2.5));
const sun = new THREE.DirectionalLight(0xffffff, 3);
sun.position.set(5, 15, 8);
scene.add(sun);

const arena = new THREE.Mesh(
  new THREE.BoxGeometry(22, 0.5, 22),
  new THREE.MeshStandardMaterial({
    color: 0x14223d, metalness: 0.6, roughness: 0.35
  })
);
arena.position.y = -0.4;
scene.add(arena);

const grid = new THREE.GridHelper(22, 22, 0x72ffaa, 0x263959);
grid.position.y = -0.14;
scene.add(grid);

// A cat-shaped spaceship.
const cat = new THREE.Group();
const white = new THREE.MeshStandardMaterial({ color: 0xe6edf7 });
const pink = new THREE.MeshStandardMaterial({ color: 0xff77bd });

const head = new THREE.Mesh(
  new THREE.SphereGeometry(0.6, 24, 16), white
);
head.scale.set(1, 0.8, 1);
cat.add(head);

for (const x of [-0.4, 0.4]) {
  const ear = new THREE.Mesh(
    new THREE.ConeGeometry(0.25, 0.6, 4), pink
  );
  ear.position.set(x, 0.55, 0);
  cat.add(ear);

  const eye = new THREE.Mesh(
    new THREE.SphereGeometry(0.09, 10, 8),
    new THREE.MeshBasicMaterial({ color: 0x112033 })
  );
  eye.position.set(x * 0.6, 0.1, 0.52);
  cat.add(eye);
}

const saucer = new THREE.Mesh(
  new THREE.CylinderGeometry(0.9, 0.65, 0.22, 32),
  new THREE.MeshStandardMaterial({
    color: 0x86ff61, metalness: 0.7, roughness: 0.25
  })
);
saucer.position.y = -0.4;
cat.add(saucer);
cat.position.y = 0.85;
scene.add(cat);

// Background stars.
const starPositions = [];
for (let i = 0; i < 700; i++) {
  starPositions.push(
    (Math.random() - 0.5) * 120,
    Math.random() * 45 + 8,
    (Math.random() - 0.5) * 120
  );
}
const starGeometry = new THREE.BufferGeometry();
starGeometry.setAttribute(
  "position", new THREE.Float32BufferAttribute(starPositions, 3)
);
scene.add(new THREE.Points(
  starGeometry,
  new THREE.PointsMaterial({ color: 0xffffff, size: 0.12 })
));

function placeOrb(orb) {
  do {
    orb.position.set(
      (Math.random() - 0.5) * 19,
      0.8,
      (Math.random() - 0.5) * 19
    );
  } while (Math.hypot(
    orb.position.x - cat.position.x,
    orb.position.z - cat.position.z
  ) < 2);
}

const orbs = [];
for (let i = 0; i < 10; i++) {
  const orb = new THREE.Mesh(
    new THREE.IcosahedronGeometry(0.35, 1),
    new THREE.MeshStandardMaterial({
      color: 0xffd45c, emissive: 0xffaa00, emissiveIntensity: 1.2
    })
  );
  placeOrb(orb);
  scene.add(orb);
  orbs.push(orb);
}

const keys = new Set();
const controls = [
  "w", "a", "s", "d",
  "arrowup", "arrowleft", "arrowdown", "arrowright"
];

addEventListener("keydown", event => {
  const key = event.key.toLowerCase();
  if (controls.includes(key)) {
    event.preventDefault();
    keys.add(key);
  }
});
addEventListener("keyup", event => keys.delete(event.key.toLowerCase()));
addEventListener("blur", () => keys.clear());

document.querySelectorAll("[data-key]").forEach(button => {
  button.onpointerdown = event => {
    event.preventDefault();
    button.setPointerCapture(event.pointerId);
    keys.add(button.dataset.key);
  };
  const release = () => keys.delete(button.dataset.key);
  button.onpointerup = release;
  button.onpointercancel = release;
  button.onlostpointercapture = release;
});

let score = 0, playing = false, deadline = 0, finishedRun = null;
let account = null, busy = false, submitted = false;

function updateSaveButton() {
  $("save").disabled =
    playing || !finishedRun || !account || busy || submitted;
}

$("start").onclick = () => {
  if (busy) return;
  score = 0;
  finishedRun = null;
  submitted = false;
  cat.position.set(0, 0.85, 0);
  orbs.forEach(placeOrb);
  deadline = performance.now() + 30000;
  playing = true;
  $("score").textContent = "0";
  $("time").textContent = "30";
  updateSaveButton();
  status("Collect as many orbs as you can in 30 seconds.");
};

async function ensureNetwork() {
  const provider = window.ethereum;
  if (!provider) throw new Error("Open this site with an EVM wallet enabled.");

  const chain = await provider.request({ method: "eth_chainId" });
  if (BigInt(chain) !== BigInt(CHAIN_ID)) {
    await provider.request({
      method: "wallet_switchEthereumChain",
      params: [{ chainId: CHAIN_ID }]
    });
  }
  const current = await provider.request({ method: "eth_chainId" });
  if (BigInt(current) !== BigInt(CHAIN_ID)) {
    throw new Error("Select chain ID 4663 in your wallet.");
  }
  return provider;
}

function showError(error) {
  status(error.code === 4902
    ? "Add chain 4663 to your wallet using verified network settings, then retry."
    : error.message || "Wallet request failed.");
}

$("connect").onclick = async () => {
  try {
    if (!window.ethereum) throw new Error("An EVM browser wallet is required.");
    await window.ethereum.request({ method: "eth_requestAccounts" });
    const provider = await ensureNetwork();
    [account] = await provider.request({ method: "eth_accounts" });
    if (!account) throw new Error("No wallet account selected.");
    $("connect").textContent = account.slice(0, 6) + "…" + account.slice(-4);
    status("Connected to chain 4663. Play a round to save a score.");
  } catch (error) {
    account = null;
    showError(error);
  }
  updateSaveButton();
};

// No contract or token approval required.
// Store a public run receipt in a zero-value transaction to your own address.
$("save").onclick = async () => {
  if (!finishedRun || busy || submitted) return;
  busy = true;
  $("start").disabled = true;
  updateSaveButton();

  try {
    const provider = await ensureNetwork();
    const accounts = await provider.request({ method: "eth_accounts" });
    if (!accounts[0]) throw new Error("Reconnect your wallet.");

    const from = accounts[0];
    const code = await provider.request({
      method: "eth_getCode", params: [from, "latest"]
    });
    if (code !== "0x") {
      throw new Error("This simple receipt mode requires a non-contract wallet.");
    }

    const receipt = JSON.stringify({
      app: "SpaceCat3D",
      version: 1,
      score: finishedRun.score,
      durationSeconds: 30,
      finishedAt: finishedRun.finishedAt
    });
    const data = "0x" + Array.from(new TextEncoder().encode(receipt))
      .map(byte => byte.toString(16).padStart(2, "0")).join("");

    status("Review the zero-value transaction and gas fee in your wallet.");
    const hash = await provider.request({
      method: "eth_sendTransaction",
      params: [{ from, to: from, value: "0x0", data }]
    });
    submitted = true;
    status("Submitted, not yet confirmed. Transaction: " + hash);
  } catch (error) {
    showError(error);
  } finally {
    busy = false;
    $("start").disabled = false;
    updateSaveButton();
  }
};

window.ethereum?.on?.("accountsChanged", () => {
  account = null;
  $("connect").textContent = "Connect wallet";
  updateSaveButton();
});
window.ethereum?.on?.("chainChanged", () => {
  account = null;
  $("connect").textContent = "Connect wallet";
  updateSaveButton();
});

let previous = performance.now();
function animate(now) {
  requestAnimationFrame(animate);
  const dt = Math.min((now - previous) / 1000, 0.05);
  previous = now;

  if (playing) {
    const remaining = Math.max(0, (deadline - now) / 1000);
    $("time").textContent = Math.ceil(remaining);

    if (remaining === 0) {
      playing = false;
      finishedRun = {
        score,
        finishedAt: new Date().toISOString()
      };
      status("Round complete! Score: " + score + ". Saving is optional.");
      updateSaveButton();
    } else {
      let x = Number(keys.has("d") || keys.has("arrowright")) -
              Number(keys.has("a") || keys.has("arrowleft"));
      let z = Number(keys.has("s") || keys.has("arrowdown")) -
              Number(keys.has("w") || keys.has("arrowup"));
      const length = Math.hypot(x, z) || 1;

      cat.position.x = THREE.MathUtils.clamp(
        cat.position.x + x / length * dt * 9, -10, 10
      );
      cat.position.z = THREE.MathUtils.clamp(
        cat.position.z + z / length * dt * 9, -10, 10
      );
      cat.rotation.z = -x * 0.15;

      for (const orb of orbs) {
        if (Math.hypot(
          cat.position.x - orb.position.x,
          cat.position.z - orb.position.z
        ) < 1) {
          score += 10;
          $("score").textContent = score;
          placeOrb(orb);
        }
      }
    }
  }

  cat.position.y = 0.85 + Math.sin(now * 0.004) * 0.1;
  orbs.forEach((orb, i) => {
    orb.rotation.y += dt;
    orb.position.y = 0.8 + Math.sin(now * 0.003 + i) * 0.15;
  });
  renderer.render(scene, camera);
}
requestAnimationFrame(animate);

addEventListener("resize", () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>

To run locally, use python -m http.server 8000 in the file’s folder, then open http://localhost:8000.

The 3D game runs in your browser; only optional score receipts go on-chain. It does not transfer $POLO, request token approvals, or deploy a contract.

robinhood-mainnet.infura.io CHAIN ID chain ID 4663

Here’s a playable Space Cat 3D browser game: dodge asteroids, collect energy, and connect a wallet to Robinhood Chain, ID 4663 (0x1237).

It uses the network details you supplied; I haven’t independently verified the endpoint’s mainnet status. The game runs on a website—not inside the blockchain—and wallet connection does not request payments or token approvals.

Save this as index.html:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Space Cat — Robinhood Chain</title>
<style>
  * { box-sizing: border-box }
  body {
    margin: 0; overflow: hidden; background: #050817; color: white;
    font-family: system-ui, sans-serif;
  }
  canvas { display: block; touch-action: none }
  #hud {
    position: fixed; top: 16px; left: 16px; right: 16px;
    display: flex; justify-content: space-between; gap: 12px;
    align-items: flex-start; pointer-events: none;
  }
  .panel {
    background: #0b122bdd; border: 1px solid #ffffff24;
    border-radius: 16px; padding: 14px; backdrop-filter: blur(8px);
  }
  h1 { font-size: 20px; margin: 0 0 6px }
  small { color: #adb8d4 }
  button {
    background: #b6ff4d; color: #111; border: 0; border-radius: 10px;
    padding: 12px 18px; font-weight: 800; cursor: pointer;
    pointer-events: auto;
  }
  button:disabled { opacity: .6; cursor: wait }
  #walletPanel { max-width: 260px; text-align: right; pointer-events: auto }
  #network { font-size: 12px; color: #adb8d4; margin-top: 8px; overflow-wrap: anywhere }
  #overlay {
    position: fixed; inset: 0; display: grid; place-items: center;
    background: #03061666; padding: 20px;
  }
  #overlay .panel { text-align: center; max-width: 430px; padding: 28px }
  #overlay h2 { font-size: 32px; margin: 0 0 12px }
  #overlay p { color: #c0cae0; line-height: 1.5 }
  #controls {
    position: fixed; bottom: 24px; left: 0; right: 0;
    display: flex; justify-content: center; gap: 70px;
  }
  #controls button { font-size: 26px; width: 80px; touch-action: manipulation }
</style>
</head>
<body>
<div id="hud">
  <div class="panel">
    <h1>SPACE CAT · $POLO</h1>
    <div id="stats">Score 0 · Shields 3 · 60s</div>
    <small>← → / A D to change lanes</small>
  </div>
  <div id="walletPanel" class="panel">
    <button id="connect">Connect wallet</button>
    <div id="network">Robinhood Chain · 4663<br>Optional · No transactions</div>
  </div>
</div>

<div id="overlay">
  <div class="panel">
    <h2 id="title">Cosmic Cat Run</h2>
    <p id="message">
      Collect green energy. Dodge purple asteroids.
      Survive for 60 seconds. Wallet connection is optional.
    </p>
    <button id="start">Launch!</button>
  </div>
</div>

<div id="controls">
  <button id="left" aria-label="Move left">←</button>
  <button id="right" aria-label="Move right">→</button>
</div>

<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js";

const $ = id => document.getElementById(id);
const CHAIN_ID = "0x1237";
const RPC_URL = "https://robinhood-mainnet.infura.io";
// Supplied endpoint; some Infura configurations require a project key.
// Wallet RPC is used below, so no project key is exposed in this file.

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x050817);
scene.fog = new THREE.Fog(0x050817, 35, 100);

const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, .1, 160);
camera.position.set(0, 7, 15);
camera.lookAt(0, 0, -15);

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
document.body.prepend(renderer.domElement);

scene.add(new THREE.HemisphereLight(0xb5ddff, 0x24103a, 2.6));
const sun = new THREE.DirectionalLight(0xffffff, 3);
sun.position.set(4, 9, 6);
scene.add(sun);

const material = (color, glow = 0x000000) =>
  new THREE.MeshStandardMaterial({
    color, emissive: glow, roughness: .45, metalness: .25
  });

const catMat = material(0xffbb65);
const darkMat = material(0x101a35);
const pinkMat = material(0xff709e);
const rockMat = material(0x9965db);
const energyMat = material(0xb6ff4d, 0x396600);

function part(parent, geometry, mat, x, y, z) {
  const mesh = new THREE.Mesh(geometry, mat);
  mesh.position.set(x, y, z);
  parent.add(mesh);
  return mesh;
}

// Space-cat character.
const cat = new THREE.Group();
scene.add(cat);
cat.position.set(0, .8, 4);
part(cat, new THREE.BoxGeometry(.95, .7, 1.2), catMat, 0, 0, 0);
part(cat, new THREE.BoxGeometry(1.05, .8, .75), catMat, 0, .62, -.2);
for (const x of [-.36, .36]) {
  part(cat, new THREE.ConeGeometry(.25, .55, 3), catMat, x, 1.23, -.2);
  part(cat, new THREE.SphereGeometry(.09, 12, 8), darkMat, x, .7, .2);
}
part(cat, new THREE.SphereGeometry(.08, 12, 8), pinkMat, 0, .5, .22);
const tail = part(cat, new THREE.CylinderGeometry(.11, .14, 1, 8),
                  catMat, .25, .35, .85);
tail.rotation.x = .8;
const board = part(cat, new THREE.BoxGeometry(1.7, .13, 1.9),
                   energyMat, 0, -.53, 0);

// Track and lane guides.
part(scene, new THREE.BoxGeometry(10, .2, 120),
     material(0x101934), 0, -.3, -45);
for (const x of [-4.8, -1.6, 1.6, 4.8]) {
  part(scene, new THREE.BoxGeometry(.045, .03, 120),
       material(0x4289bb, 0x12314a), x, -.18, -45);
}

// Star field.
const starPositions = new Float32Array(1200 * 3);
for (let i = 0; i < starPositions.length; i += 3) {
  starPositions[i] = (Math.random() - .5) * 150;
  starPositions[i + 1] = Math.random() * 65 + 5;
  starPositions[i + 2] = -Math.random() * 140;
}
const starsGeometry = new THREE.BufferGeometry();
starsGeometry.setAttribute("position", new THREE.BufferAttribute(starPositions, 3));
scene.add(new THREE.Points(starsGeometry,
  new THREE.PointsMaterial({ color: 0xdbeaff, size: .14 })));

const rockGeometry = new THREE.IcosahedronGeometry(.7, 0);
const energyGeometry = new THREE.OctahedronGeometry(.45, 0);
const objects = [];
const lanes = [-3.2, 0, 3.2];
let lane = 1, score = 0, shields = 3, remaining = 60;
let running = false, spawnTimer = 0, invulnerable = 0;

function move(direction) {
  if (running) lane = THREE.MathUtils.clamp(lane + direction, 0, 2);
}
$("left").onclick = () => move(-1);
$("right").onclick = () => move(1);
addEventListener("keydown", e => {
  if (["ArrowLeft", "ArrowRight", "a", "A", "d", "D"].includes(e.key)) {
    e.preventDefault();
    if (e.repeat) return;
    move(["ArrowLeft", "a", "A"].includes(e.key) ? -1 : 1);
  }
});

function updateHUD() {
  $("stats").textContent =
    `Score ${score} · Shields ${shields} · ${Math.ceil(remaining)}s`;
}

function start() {
  for (const object of objects) scene.remove(object);
  objects.length = 0;
  lane = 1; score = 0; shields = 3; remaining = 60;
  spawnTimer = 0; invulnerable = 0;
  cat.position.x = 0; cat.visible = true;
  running = true;
  $("overlay").style.display = "none";
  updateHUD();
}
$("start").onclick = start;

function finish(won) {
  running = false;
  cat.visible = true;
  $("title").textContent = won ? "Mission complete!" : "Cat rescued!";
  $("message").textContent =
    `Final score: ${score}. ` +
    (won ? "You survived the asteroid belt." : "Try again and dodge those asteroids.");
  $("start").textContent = "Play again";
  $("overlay").style.display = "grid";
}

function spawn() {
  // One object per wave always leaves two lanes open.
  const energy = Math.random() < .45;
  const object = new THREE.Mesh(
    energy ? energyGeometry : rockGeometry,
    energy ? energyMat : rockMat
  );
  object.position.set(lanes[Math.floor(Math.random() * 3)], .8, -65);
  object.userData.energy = energy;
  objects.push(object);
  scene.add(object);
}

let previous = performance.now();
function frame(now) {
  requestAnimationFrame(frame);
  const dt = Math.min((now - previous) / 1000, .05);
  previous = now;

  cat.position.y = .8 + Math.sin(now * .006) * .08;
  cat.position.x = THREE.MathUtils.lerp(cat.position.x, lanes[lane], 1 - Math.exp(-14 * dt));
  cat.rotation.z = (cat.position.x - lanes[lane]) * .12;
  tail.rotation.z = Math.sin(now * .005) * .25;

  if (running) {
    remaining = Math.max(0, remaining - dt);
    invulnerable = Math.max(0, invulnerable - dt);
    cat.visible = !invulnerable || Math.floor(now / 90) % 2 === 0;
    const speed = 19 + (60 - remaining) * .22;

    spawnTimer -= dt;
    if (spawnTimer <= 0) {
      spawn();
      spawnTimer = .65 + Math.random() * .25;
    }

    for (let i = objects.length - 1; i >= 0; i--) {
      const object = objects[i];
      object.position.z += speed * dt;
      object.rotation.x += dt;
      object.rotation.y += dt * 1.5;

      const hit = Math.abs(object.position.z - cat.position.z) < 1.15 &&
                  Math.abs(object.position.x - cat.position.x) < 1;

      if (hit) {
        if (object.userData.energy) score += 10;
        else if (!invulnerable) {
          shields--;
          invulnerable = 1.15;
        }
      }
      if (hit || object.position.z > 12) {
        scene.remove(object);
        objects.splice(i, 1);
      }
    }

    updateHUD();
    if (shields <= 0) finish(false);
    else if (remaining <= 0) finish(true);
  }

  renderer.render(scene, camera);
}
requestAnimationFrame(frame);

addEventListener("resize", () => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});

// Optional blockchain connection. No signatures, approvals, or transactions.
const provider = window.ethereum;
let connected = false;

async function refreshNetwork() {
  if (!provider || !connected) return;
  try {
    const chain = await provider.request({ method: "eth_chainId" });
    if (BigInt(chain) !== BigInt(CHAIN_ID)) {
      $("network").textContent = "Wrong network. Connect to chain 4663.";
      return;
    }
    const accounts = await provider.request({ method: "eth_accounts" });
    if (!accounts.length) {
      connected = false;
      $("connect").textContent = "Connect wallet";
      $("network").textContent = "Wallet disconnected";
      return;
    }
    const block = await provider.request({ method: "eth_blockNumber" });
    const address = accounts[0];
    $("connect").textContent = `${address.slice(0, 6)}…${address.slice(-4)}`;
    $("network").textContent =
      `Chain 4663 · Block ${BigInt(block).toString()} · Read-only`;
  } catch {
    $("network").textContent = "Unable to read network. Check your wallet RPC.";
  }
}

$("connect").onclick = async () => {
  if (!provider) {
    $("network").textContent =
      "Open this page in an EVM wallet browser or enable a wallet extension.";
    return;
  }
  $("connect").disabled = true;
  try {
    await provider.request({
      method: "wallet_switchEthereumChain",
      params: [{ chainId: CHAIN_ID }]
    });
    await provider.request({ method: "eth_requestAccounts" });
    connected = true;
    await refreshNetwork();
  } catch (error) {
    const code = error.code ?? error.data?.originalError?.code;
    $("network").textContent = code === 4902
      ? `Add chain 4663 to your wallet using official network metadata. Supplied RPC: ${RPC_URL}. Then reconnect.`
      : code === 4001
        ? "Connection cancelled. You can still play."
        : `Connection failed: ${error.message || "Check wallet settings."}`;
  } finally {
    $("connect").disabled = false;
  }
};

provider?.on?.("chainChanged", refreshNetwork);
provider?.on?.("accountsChanged", refreshNetwork);
setInterval(refreshNetwork, 15000);
</script>
</body>
</html>

Run it

  1. Save the file in a folder.
  2. In that folder, run python3 -m http.server 8080.
  3. Open http://localhost:8080.

For a public game, deploy the file to a static host such as Cloudflare Pages, Netlify, or GitHub Pages.

Included: 3D gameplay, desktop/mobile controls, wallet connection, chain checking, and live block reads. Scores remain local and unverified; this version does not deploy a contract or issue tokens.

MORE GRAPHIC AND 3D

Let’s make it look like a neon space arcade: glowing engines, a detailed 3D cat ship, a ringed planet, asteroid explosions, shadows, and a moving chase camera.

Replace your previous index.html with this. Wallet connection remains optional on chain 4663; no payments or approvals.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>SPACE CAT — Neon Orbit</title>
<style>
*{box-sizing:border-box}
body{margin:0;overflow:hidden;background:#020410;color:#fff;font:14px system-ui}
canvas{display:block}
#hud{position:fixed;inset:18px 18px auto;display:flex;justify-content:space-between;gap:12px;pointer-events:none}
.panel{background:linear-gradient(135deg,#0c163add,#101426aa);border:1px solid #82eaff33;border-radius:18px;padding:16px;backdrop-filter:blur(14px);box-shadow:0 10px 50px #0005}
h1{font-size:21px;letter-spacing:3px;margin:0 0 8px}
small{color:#a2bad6}
#stats{font-size:16px;color:#aaffee;margin-bottom:6px}
button{border:1px solid #ffffff30;background:linear-gradient(135deg,#9affcf,#55bbff);color:#052033;border-radius:12px;padding:12px 18px;font-weight:800;cursor:pointer;pointer-events:auto}
button:disabled{opacity:.5}
#walletBox{text-align:right;max-width:240px}
#network{font-size:11px;color:#9db4d1;margin-top:8px;overflow-wrap:anywhere}
#overlay{position:fixed;inset:0;display:grid;place-items:center;padding:20px;background:#02061577}
#overlay .panel{text-align:center;max-width:480px;padding:36px}
#overlay h2{font-size:clamp(30px,7vw,48px);letter-spacing:4px;margin:0;background:linear-gradient(90deg,#aaffde,#91aaff,#ffa4ee);background-clip:text;color:transparent}
#overlay p{line-height:1.7;color:#b7c9e4}
#start{font-size:16px;padding:15px 32px}
#controls{position:fixed;bottom:24px;left:0;right:0;display:flex;justify-content:center;gap:90px}
#controls button{width:76px;font-size:25px;background:#13294bcc;color:#aaffee;touch-action:manipulation}
#vignette{position:fixed;inset:0;pointer-events:none;box-shadow:inset 0 0 130px #0009}
#flash{position:fixed;inset:0;pointer-events:none;background:#ff3366;opacity:0}
@media(max-width:600px){#hud{inset:10px}.panel{padding:11px}h1{font-size:15px;letter-spacing:1px}#stats{font-size:13px}#walletBox{max-width:155px}#connect{padding:9px}}
</style>
<script type="importmap">
{
  "imports":{
    "three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
    "three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
  }
}
</script>
</head>
<body>
<div id="vignette"></div>
<div id="flash"></div>
<div id="hud">
  <div class="panel">
    <h1>SPACE CAT / NEON ORBIT</h1>
    <div id="stats">0000 · SHIELDS 3 · 60s</div>
    <small>A D / ← → · Collect cyan crystals</small>
  </div>
  <div id="walletBox" class="panel">
    <button id="connect">Connect wallet</button>
    <div id="network">Robinhood Chain · 4663<br>Optional · No transactions</div>
  </div>
</div>
<div id="overlay">
  <div class="panel">
    <h2>NEON ORBIT</h2>
    <p>A cat. A starfighter. An asteroid highway.<br>
    Collect energy crystals, dodge space rocks, and survive 60 seconds.</p>
    <p id="result">Three lanes. Three shields. One cosmic adventure.</p>
    <button id="start">LAUNCH SHIP</button>
  </div>
</div>
<div id="controls">
  <button id="left" aria-label="Move left">←</button>
  <button id="right" aria-label="Move right">→</button>
</div>

<script type="module">
import * as THREE from "three";
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";
import { OutputPass } from "three/addons/postprocessing/OutputPass.js";

const $ = id => document.getElementById(id);
const mobile = matchMedia("(max-width:700px)").matches;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x030516);
scene.fog = new THREE.FogExp2(0x070a21, .007);

const camera = new THREE.PerspectiveCamera(62,innerWidth/innerHeight,.1,400);
camera.position.set(0,6.5,15);

const renderer = new THREE.WebGLRenderer({antialias:true,powerPreference:"high-performance"});
renderer.setSize(innerWidth,innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio,mobile?1.25:1.7));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.15;
document.body.prepend(renderer.domElement);

const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene,camera));
const bloom = new UnrealBloomPass(
  new THREE.Vector2(innerWidth,innerHeight),.85,.55,.85
);
composer.addPass(bloom);
composer.addPass(new OutputPass());

scene.add(new THREE.HemisphereLight(0x92cfff,0x3c1855,2));
const sun = new THREE.DirectionalLight(0xd8eaff,3);
sun.position.set(-12,24,12);
sun.castShadow = true;
sun.shadow.mapSize.set(1024,1024);
Object.assign(sun.shadow.camera,{left:-16,right:16,top:20,bottom:-20,near:1,far:80});
sun.shadow.bias = -.001;
scene.add(sun);

const rim = new THREE.DirectionalLight(0xff55c8,2);
rim.position.set(10,6,-20);
scene.add(rim);

const mat = (color,metalness=.4,roughness=.4) =>
  new THREE.MeshStandardMaterial({color,metalness,roughness});
const glow = (color,power=3) =>
  new THREE.MeshStandardMaterial({color,emissive:color,emissiveIntensity:power});

const hull = mat(0xdde6f7,.8,.24);
const dark = mat(0x111b36,.75,.3);
const orange = mat(0xffb65d,.1,.6);
const pink = mat(0xff739b,.1,.5);
const cyan = glow(0x33ffdd,3);
const violet = glow(0x8b55ff,2.5);

function mesh(parent,geometry,material,x=0,y=0,z=0){
  const object = new THREE.Mesh(geometry,material);
  object.position.set(x,y,z);
  object.castShadow = true;
  object.receiveShadow = true;
  parent.add(object);
  return object;
}

// Detailed starfighter and cat pilot.
const ship = new THREE.Group();
ship.position.set(0,1.2,4);
scene.add(ship);

const body = mesh(ship,new THREE.SphereGeometry(1,32,20),hull,0,0,0);
body.scale.set(.83,.36,1.45);
mesh(ship,new THREE.BoxGeometry(.55,.22,2.1),dark,0,-.12,.25);

for(const side of [-1,1]){
  const wing = mesh(ship,new THREE.BoxGeometry(1.45,.12,1),hull,side*1.15,-.08,.25);
  wing.rotation.z = side*.1;
  wing.rotation.y = side*-.25;
  mesh(ship,new THREE.BoxGeometry(.08,.06,1),cyan,side*1.77,0,.35);

  const engine = mesh(ship,new THREE.CylinderGeometry(.24,.31,.85,20),dark,side*.95,-.03,1);
  engine.rotation.x = Math.PI/2;
  const nozzle = mesh(ship,new THREE.TorusGeometry(.21,.065,10,24),cyan,side*.95,-.03,1.45);
  nozzle.castShadow = false;
}

const flames=[];
for(const side of [-1,1]){
  const flame = mesh(ship,new THREE.ConeGeometry(.2,1.8,16),cyan,side*.95,-.03,2.3);
  flame.rotation.x = Math.PI/2;
  flame.castShadow = false;
  flames.push(flame);
}

const pilot = new THREE.Group();
pilot.position.set(0,.45,-.1);
ship.add(pilot);
const head = mesh(pilot,new THREE.SphereGeometry(.47,24,20),orange,0,.23,0);
head.scale.set(1,.93,.85);

for(const side of [-1,1]){
  const ear = mesh(pilot,new THREE.ConeGeometry(.22,.45,3),orange,side*.3,.67,-.04);
  ear.rotation.z = -side*.14;
  mesh(pilot,new THREE.ConeGeometry(.12,.27,3),pink,side*.3,.69,.065);
  mesh(pilot,new THREE.SphereGeometry(.085,12,10),dark,side*.18,.27,.36);
  mesh(pilot,new THREE.SphereGeometry(.024,8,8),cyan,side*.16,.295,.42);
  for(let j=0;j<3;j++){
    const whisker = mesh(pilot,new THREE.BoxGeometry(.26,.012,.014),hull,side*.4,.06+j*.055,.35);
    whisker.rotation.z = side*(j-1)*.15;
  }
}
mesh(pilot,new THREE.SphereGeometry(.055,12,8),pink,0,.12,.41);

const canopy = mesh(ship,new THREE.SphereGeometry(.79,32,24),
  new THREE.MeshPhysicalMaterial({
    color:0x6edaff,metalness:0,roughness:.12,
    transparent:true,opacity:.16,depthWrite:false,
    side:THREE.FrontSide
  }),0,.58,-.1);
canopy.scale.set(.92,1,.9);
canopy.castShadow = false;

const engineLight = new THREE.PointLight(0x32ffdd,8,9,2);
engineLight.position.set(0,.3,2);
ship.add(engineLight);

// Neon highway.
const road = mesh(scene,new THREE.BoxGeometry(12,.3,180),
  mat(0x101a33,.8,.28),0,-.35,-75);
road.castShadow = false;

for(const x of [-6,-2,2,6]){
  const strip = mesh(scene,new THREE.BoxGeometry(.045,.035,180),
    x===-6||x===6?violet:cyan,x,-.17,-75);
  strip.castShadow = false;
}

const markers=[];
for(let i=0;i<34;i++){
  const bar = mesh(scene,new THREE.BoxGeometry(11.9,.025,.065),
    glow(0x244a7b,.8),0,-.17,-i*5);
  bar.castShadow = false;
  markers.push(bar);
}

// Huge ringed planet in the distance.
const planet = new THREE.Group();
planet.position.set(37,27,-115);
scene.add(planet);
mesh(planet,new THREE.SphereGeometry(18,64,48),mat(0x5a69b9,.15,.85));

const atmosphere = mesh(planet,new THREE.SphereGeometry(18.5,48,32),
  new THREE.MeshBasicMaterial({
    color:0x687fff,transparent:true,opacity:.07,
    side:THREE.BackSide,depthWrite:false
  }));
atmosphere.castShadow=false;

for(let i=0;i<4;i++){
  const ring = mesh(planet,new THREE.RingGeometry(23+i*2,24.2+i*2,128),
    new THREE.MeshBasicMaterial({
      color:[0x9d99ee,0x6477c8,0xcaa2ef,0x527dae][i],
      side:THREE.DoubleSide,transparent:true,opacity:.5
    }));
  ring.rotation.set(1.12,.3,.22);
  ring.castShadow=false;
}

const moon = mesh(scene,new THREE.SphereGeometry(7,32,24),
  mat(0x913c76,.1,.9),-38,16,-95);

// Procedural stars.
const starCount=mobile?1100:2300;
const starData=new Float32Array(starCount*3);
for(let i=0;i<starCount;i++){
  starData[i*3]=(Math.random()-.5)*280;
  starData[i*3+1]=Math.random()*120-20;
  starData[i*3+2]=-Math.random()*270;
}
const starGeo=new THREE.BufferGeometry();
starGeo.setAttribute("position",new THREE.BufferAttribute(starData,3));
const stars=new THREE.Points(starGeo,new THREE.PointsMaterial({
  color:0xbbdfff,size:.2,sizeAttenuation:true
}));
scene.add(stars);

// Distant geometric structures provide depth and parallax.
const scenery=[];
const pillarGeo=new THREE.OctahedronGeometry(1,0);
const pillarMat=mat(0x23375f,.7,.4);
for(let i=0;i<32;i++){
  const side=i%2?1:-1;
  const p=mesh(scene,pillarGeo,pillarMat,
    side*(11+Math.random()*18),Math.random()*9,-i*6);
  p.scale.set(1+Math.random()*2,2+Math.random()*6,1+Math.random()*2);
  p.rotation.set(Math.random(),Math.random(),Math.random());
  scenery.push(p);
}

// Shared geometries keep object creation lightweight.
const rockGeo=new THREE.IcosahedronGeometry(.8,1);
const positions=rockGeo.attributes.position;
for(let i=0;i<positions.count;i++){
  const x=positions.getX(i),y=positions.getY(i),z=positions.getZ(i);
  const factor=1+.16*Math.sin(x*17+y*11+z*7);
  positions.setXYZ(i,x*factor,y*factor,z*factor);
}
rockGeo.computeVertexNormals();
const rockMat=mat(0x625275,.45,.85);
const crystalGeo=new THREE.OctahedronGeometry(.5);
const particleGeo=new THREE.TetrahedronGeometry(.09);
const ringGeo=new THREE.TorusGeometry(.75,.035,8,32);
const objects=[],particles=[];
const lanes=[-4,0,4];

let lane=1,score=0,shields=3,time=60;
let running=false,spawnTimer=0,invincible=0,shake=0,damageFlash=0;

function burst(position,color,count){
  for(let i=0;i<count;i++){
    const p=mesh(scene,particleGeo,color,position.x,position.y,position.z);
    p.castShadow=false;
    p.userData={
      velocity:new THREE.Vector3(
        (Math.random()-.5)*10,
        (Math.random()-.3)*8,
        (Math.random()-.5)*10
      ),
      life:.5+Math.random()*.5
    };
    particles.push(p);
  }
}

function spawn(){
  const collectible=Math.random()<.43;
  const group=new THREE.Group();
  group.position.set(lanes[Math.floor(Math.random()*3)],1.2,-95);
  group.userData.collectible=collectible;
  const core=mesh(group,collectible?crystalGeo:rockGeo,collectible?cyan:rockMat);
  if(collectible){
    const halo=mesh(group,ringGeo,violet);
    halo.rotation.x=Math.PI/2;
    halo.castShadow=false;
  }else{
    core.rotation.set(Math.random()*3,Math.random()*3,0);
    core.scale.set(1.1,1.2,.95);
  }
  scene.add(group);
  objects.push(group);
}

function move(direction){
  if(running) lane=THREE.MathUtils.clamp(lane+direction,0,2);
}
$("left").onclick=()=>move(-1);
$("right").onclick=()=>move(1);
addEventListener("keydown",e=>{
  const key=e.key.toLowerCase();
  if(["arrowleft","arrowright","a","d"].includes(key)){
    e.preventDefault();
    if(!e.repeat) move(key==="a"||key==="arrowleft"?-1:1);
  }
});

function hud(){
  $("stats").textContent=
    `${String(score).padStart(4,"0")} · SHIELDS ${shields} · ${Math.ceil(time)}s`;
}
function clearObjects(list){
  for(const object of list) scene.remove(object);
  list.length=0;
}
$("start").onclick=()=>{
  clearObjects(objects);
  clearObjects(particles);
  lane=1;score=0;shields=3;time=60;
  spawnTimer=.5;invincible=0;shake=0;damageFlash=0;
  ship.position.x=0;ship.visible=true;running=true;
  $("overlay").style.display="none";
  hud();
};
function finish(){
  running=false;
  ship.visible=true;
  $("result").textContent=shields>0
   

Anyone who has launched a token can talk to this model.

Backing model

GPT-6 Astra

openai/gpt-6-astra

More tokens →

GPT-6 Astra is OpenAI's flagship model for demanding end-to-end work. It is suited for advanced analysis, software engineering, deep research, scientific work, and document creation, with particular strengths in long-hor...

Context
1050K
Pool
$8.27
Input
$10.00/M
Output
$50.00/M

Recent trades

TimeSideETHUSDPOLOTraderTx
53m agoSell0.0125$31.557,550,9730x8f10…f9960x49d…536
57m agoBuy0.0133$33.537,550,9730x2b5f…e8b60x8eb…51c
1h agoSell0.0093$23.405,611,7050xc6a2…c0210x647…549
1h agoSell0.0095$23.945,676,1410xe4f8…b1740x5fe…3e3
1h agoBuy0.0100$25.165,611,7050xc6a2…c0210xc46…c94
1h agoBuy0.0100$25.165,676,1410xe4f8…b1740x484…927
1h agoBuy0.0098$24.765,651,8590x6505…40dc0x811…26a
1h agoSell0.0056$14.203,452,3260x91d8…05b40x161…bd6
1h agoBuy0.0060$15.093,452,3260xe33e…29480x599…05e