{"id":22998476,"url":"https://github.com/tablelandnetwork/example-canvas-game","last_synced_at":"2025-04-02T13:24:42.392Z","repository":{"id":60464311,"uuid":"541827062","full_name":"tablelandnetwork/example-canvas-game","owner":"tablelandnetwork","description":"Example of building with Tableland from a Smart Contract","archived":false,"fork":false,"pushed_at":"2023-05-10T05:07:35.000Z","size":1321,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-25T17:03:25.575Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tablelandnetwork.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-09-26T23:45:49.000Z","updated_at":"2023-09-30T04:40:16.000Z","dependencies_parsed_at":"2023-02-09T07:02:20.007Z","dependency_job_id":null,"html_url":"https://github.com/tablelandnetwork/example-canvas-game","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tablelandnetwork%2Fexample-canvas-game","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tablelandnetwork%2Fexample-canvas-game/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tablelandnetwork%2Fexample-canvas-game/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tablelandnetwork%2Fexample-canvas-game/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tablelandnetwork","download_url":"https://codeload.github.com/tablelandnetwork/example-canvas-game/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246821082,"owners_count":20839363,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-15T06:13:32.418Z","updated_at":"2025-04-02T13:24:42.371Z","avatar_url":"https://github.com/tablelandnetwork.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Canvas Game\n\n\u003e Dynamic global game state controlled by user-owned game NFTs.\n\n## Background\n\nTableland makes it possible for an event-driven architecture that dynamically updates NFT metadata. In this tutorial, users are able to openly mint \"pixel\" NFTs that mutate a global game state table. The `CanvasGame` contract owns a Tableland table and writes all mutating SQL statements, but the mutating SQL statement first check the caller's token ownership before changing any metadata values for `x` and `y` pixel coordinates on a 512x512 canvas.\n\nA metadata table holds data for the token ID and these coordinates, allowing for ERC721 metadata to be composed:\n\n```sql\nSELECT\n  json_object(\n    'name', 'Token #' || id,\n    'external_url', '\u003cexternal_url\u003e',\n    'attributes',\n    json_array(\n      json_object(\n        'display_type', 'number',\n        'trait_type', 'x',\n        'value', x\n      ),\n      json_object(\n        'display_type', 'number',\n        'trait_type', 'y',\n        'value', y\n      )\n    )\n  )\nFROM\n  \u003cprefix_chainId_tableId\u003e\nWHERE\n  id = \u003ctokenId\u003e\n```\n\nFor a detailed walkthrough, [check out the docs](https://docs.tableland.xyz/tutorials/dynamic-nft-solidity).\n\n### Project structure\n\nIf you're following along, the following outlines steps needed to recreate the structure in this repository. These steps are not needed if you simply clone or fork this repo.\n\nFirst, set up a Hardhat project by creating a directory, `cd` into it, and then run the following:\n\n```bash\nnpx hardhat\n```\n\nYou'll need the following dependencies:\n\n- `@tableland/evm`\n- `@openzeppelin/contracts-upgradeable`\n\nDo this will the following command:\n\n```bash\nnpm i @tableland/evm @openzeppelin/contracts-upgradeable\n```\n\nAnd development dependencies of `@tableland/local`, `@tableland/hardhat`, and `dotenv`:\n\n```bash\nnpm i -D @tableland/local @tableland/hardhat dotenv\n```\n\nFrom there, the `contracts/Lock.sol` (and the contract name) should be changed to `contracts/CanvasGame.sol`, and four scripts should be created in the `scripts` directory:\n\n- `deploy.ts`\n- `move.ts`\n- `upgrade.ts`\n- `verify.ts`\n\nBe sure to also update the `config` object in `hardhat.config.ts` with information needed for the Tableland Hardhat plugin.\n\n```js\n// ...\nlocalTableland: {\n  silent: false,\n  verbose: false,\n},\n// ...\n```\n\nThe linked tutorial on the docs site walks through the rest of the setup and code.\n\n## Usage\n\nIf you're simply cloning this repo, first, install dependencies with `npm`:\n\n```bash\nnpm install\n```\n\nYou'll also want to ensure you `.env` variables set up—copy the `.env.example` into `.env` and update the placeholders if you plan to deploy to a live network, such as Polygon Mumbai: `POLYGON_MUMBAI_PRIVATE_KEY`, `POLYGON_MUMBAI_API_KEY`, and `POLYGONSCAN_API_KEY`.\n\nIf you are developing locally, you'll first want to start a local Hardhat and Tableland node:\n\n```bash\nnpx hardhat node --network local-tableland\n```\n\nThen, you can run the deploy script—**be sure to update the `deployments`** variable in `hardhat.config.ts` with the value logged in the script:\n\n```bash\nnpx hardhat run scripts/deploy.ts --network localhost\n```\n\nThat is, update this with your data:\n\n```js\nexport const deployments: { [key: string]: string } = {\n  localhost: \"0x5FC8d32690cc91D4c39d9d3abcBD16989F875707\", // If it's the first deployed contract, this is deterministic\n  maticmum: \"\", // Update this with your proxy contract deployment\n  // And/or, add a different network key\n};\n```\n\nThe following scripts are also available:\n\n- `move.ts`: Move your owned pixel NFT's `x` and `y` coordinates.\n- `upgrade.ts`: Upgrade your contract upon code changes.\n- `verify.ts`: Verify the contract on live networks.\n\nIf you would like to deploy to Polygon Mumbai, as an example, simply change the `--network` flag:\n\n```bash\nnpx hardhat run scripts/deploy.ts --network maticmum\n```\n\n### Testing\n\nTests use Local Tableland and can be ran with `npm run test`, which runs the following under the hood:\n\n```bash\nnpx hardhat --network localhost test\n```\n\nThis spins up a Tableland and Hardhat node temporarily, so be sure to close out any running instances of these nodes when running tests.\n\n### Example output\n\nThe following contract was deployed on Polygon Mumbai: [`0xEB5865EF3949585324c465eC9ba5C7777f455488`](https://mumbai.polygonscan.com/address/0xEB5865EF3949585324c465eC9ba5C7777f455488#writeProxyContract). An ERC721 example query for token `0` can be viewed [here](https://testnets.tableland.network/api/v1/query?unwrap=true\u0026extract=true\u0026statement=SELECT%20json_object%28%27name%27%2C%20%27Token%20%23%27%20%7C%7C%20id%2C%20%27external_url%27%2C%20'not.implemented.com'%2C%20%27attributes%27%2Cjson_array%28json_object%28%27display_type%27%2C%20%27number%27%2C%20%27trait_type%27%2C%20%27x%27%2C%20%27value%27%2C%20x%29%2Cjson_object%28%27display_type%27%2C%20%27number%27%2C%20%27trait_type%27%2C%20%27y%27%2C%20%27value%27%2C%20y%29%29%29%20FROM%20canvas_80001_6076%20WHERE%20id=0).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftablelandnetwork%2Fexample-canvas-game","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftablelandnetwork%2Fexample-canvas-game","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftablelandnetwork%2Fexample-canvas-game/lists"}