StarknetDojo入门:安装、编译、部署与交互Dojo是一个社区驱动的开源项目,旨在为开发者提供构建、部署和管理Starknet链上游戏的基础设施。它提供了一套工具和框架,帮助开发者快速构建和部署复杂的链上游戏,同时提供了一套丰富的API和组件,帮助开发者实现各种游戏功能。什
Dojo 是一个社区驱动的开源项目,旨在为开发者提供构建、部署和管理 Starknet 链上游戏的基础设施。它提供了一套工具和框架,帮助开发者快速构建和部署复杂的链上游戏,同时提供了一套丰富的 API 和组件,帮助开发者实现各种游戏功能。
Dojo 是一个社区驱动的开源可证明游戏引擎,为构建可验证游戏和自主世界提供了全面的工具包。
链上游戏,包括状态和逻辑,都完全位于公共区块链上,由智能合约定义。
可证明的游戏是在 zkvms 上设计的,并且可以验证其执行情况,从而实现客户端游戏。
Dojo 使得在 Starknet 链上构建自主世界的游戏变得非常容易。
Dark Forest
# asdf plugin-add dojo
asdf plugin add dojo https://github.com/dojoengine/asdf-dojo
# Install the latest version of Dojo
asdf install dojo latest   
# check installed version
asdf list dojo

sozo init dojo-starter
 ⛩️ ====== STARTING ====== ⛩️ 
Setting up project directory tree...
warn: Couldn't find template for your current sozo version. Getting the latest version 
            instead.
🎉 Successfully created a new ⛩️ Dojo project!
====== SETUP COMPLETE! ======
To start using your new project, try running: `sozo build`
cd dojo-starter/
ccCode/starknet-code/dojo-starter via 🅒 base 
➜ sozo build            
    Updating git repository https://github.com/dojoengine/dojo
   Compiling dojo_starter v1.0.9 (/Users/qiaopengjun/Code/starknet-code/dojo-starter/Scarb.toml)
    Finished `dev` profile target(s) in 25 secondsCode/starknet-code/dojo-starter via 🅒 base 
➜ katana --version
katana 1.0.9 (04b5f02)
Code/starknet-code/dojo-starter via 🅒 base 
➜ katana --dev --dev.no-fee                         
██╗  ██╗ █████╗ ████████╗ █████╗ ███╗   ██╗ █████╗
██║ ██╔╝██╔══██╗╚══██╔══╝██╔══██╗████╗  ██║██╔══██╗
█████╔╝ ███████║   ██║   ███████║██╔██╗ ██║███████║
██╔═██╗ ██╔══██║   ██║   ██╔══██║██║╚██╗██║██╔══██║
██║  ██╗██║  ██║   ██║   ██║  ██║██║ ╚████║██║  ██║
╚═╝  ╚═╝╚═╝  ╚═╝   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═══╝╚═╝  ╚═╝
PREDEPLOYED CONTRACTS
==================
| Contract        | ETH Fee Token
| Address         | 0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7
| Class Hash      | 0x00a2475bc66197c751d854ea8c39c6ad9781eb284103bcd856b58e6b500078ac
| Contract        | STRK Fee Token
| Address         | 0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d
| Class Hash      | 0x00a2475bc66197c751d854ea8c39c6ad9781eb284103bcd856b58e6b500078ac
| Contract        | Universal Deployer
| Address         | 0x41a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf
| Class Hash      | 0x07b3e05f48f0c69e4a65ce5e076a66271a527aff2c34ce1083ec6e1526997a69
| Contract        | Account Contract
| Class Hash      | 0x07dc7899aa655b0aae51eadff6d801a58e97dd99cf4666ee59e704249e51adf2
PREFUNDED ACCOUNTS
==================
| Account address |  0x127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec
| Private key     |  0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912
| Public key      |  0x33246ce85ebdc292e6a5c5b4dd51fab2757be34b8ffda847ca6925edf31cb67
| Account address |  0x13d9ee239f33fea4f8785b9e3870ade909e20a9599ae7cd62c1c292b73af1b7
| Private key     |  0x1c9053c053edf324aec366a34c6901b1095b07af69495bffec7d7fe21effb1b
| Public key      |  0x4c339f18b9d1b95b64a6d378abd1480b2e0d5d5bd33cd0828cbce4d65c27284
| Account address |  0x17cc6ca902ed4e8baa8463a7009ff18cc294fa85a94b4ce6ac30a9ebd6057c7
| Private key     |  0x14d6672dcb4b77ca36a887e9a11cd9d637d5012468175829e9c6e770c61642
| Public key      |  0x16e375df37a7653038bd9eccd767e780c2c4d4c66b4c85f455236a3fd75673a
| Account address |  0x2af9427c5a277474c079a1283c880ee8a6f0f8fbf73ce969c08d88befec1bba
| Private key     |  0x1800000000300000180000000000030000000000003006001800006600
| Public key      |  0x2b191c2f3ecf685a91af7cf72a43e7b90e2e41220175de5c4f7498981b10053
| Account address |  0x359b9068eadcaaa449c08b79a367c6fdfba9448c29e96934e3552dab0fdd950
| Private key     |  0x2bbf4f9fd0bbb2e60b0316c1fe0b76cf7a4d0198bd493ced9b8df2a3a24d68a
| Public key      |  0x640466ebd2ce505209d3e5c4494b4276ed8f1cde764d757eb48831961f7cdea
| Account address |  0x4184158a64a82eb982ff702e4041a49db16fa3a18229aac4ce88c832baf56e4
| Private key     |  0x6bf3604bcb41fed6c42bcca5436eeb65083a982ff65db0dc123f65358008b51
| Public key      |  0x4b076e402835913e3f6812ed28cef8b757d4643ebf2714471a387cb10f22be3
| Account address |  0x42b249d1633812d903f303d640a4261f58fead5aa24925a9efc1dd9d76fb555
| Private key     |  0x283d1e73776cd4ac1ac5f0b879f561bded25eceb2cc589c674af0cec41df441
| Public key      |  0x73c8a29ba0e6a368422d0551b3f45a30a27166b809ba07a41a1bc434b000ba7
| Account address |  0x4e0b838810cb1a355beb7b3d894ca0e98ee524309c3f8b7cccb15a48e6270e2
| Private key     |  0x736adbbcdac7cc600f89051db1abbc16b9996b46f6b58a9752a11c1028a8ec8
| Public key      |  0x570258e7277eb345ab80803c1dc5847591efd028916fc826bc7cd47ccd8f20d
| Account address |  0x5b6b8189bb580f0df1e6d6bec509ff0d6c9be7365d10627e0cf222ec1b47a71
| Private key     |  0x33003003001800009900180300d206308b0070db00121318d17b5e6262150b
| Public key      |  0x4c0f884b8e5b4f00d97a3aad26b2e5de0c0c76a555060c837da2e287403c01d
| Account address |  0x6677fe62ee39c7b07401f754138502bab7fac99d2d3c5d37df7d1c6fab10819
| Private key     |  0x3e3979c1ed728490308054fe357a9f49cf67f80f9721f44cc57235129e090f4
| Public key      |  0x1e8965b7d0b20b91a62fe515dd991dc9fcb748acddf6b2cf18cec3bdd0f9f9a
ACCOUNTS SEED
=============
0
2025-01-01T04:43:43.417844Z  INFO katana_node: Starting node. chain=0x4b4154414e41
2025-01-01T04:43:43.418179Z  INFO rpc: RPC server started. addr=127.0.0.1:5050
2025-01-01T05:51:43.829197Z DEBUG server: method="starknet_getBlockWithTxHashes"
2025-01-01T05:51:43.843903Z DEBUG server: method="starknet_chainId"
2025-01-01T05:51:47.045115Z DEBUG server: method="starknet_getBlockWithTxHashes"
2025-01-01T05:51:47.045518Z DEBUG server: method="starknet_specVersion"
2025-01-01T05:51:47.045760Z DEBUG server: method="starknet_chainId"
2025-01-01T05:51:47.045975Z DEBUG server: method="starknet_getClassHashAt"
2025-01-01T05:51:47.376701Z DEBUG server: method="starknet_chainId"
2025-01-01T05:51:47.377285Z DEBUG server: method="starknet_getClassHashAt"
2025-01-01T05:51:47.975383Z DEBUG server: method="starknet_getClass"
2025-01-01T05:51:47.976854Z DEBUG server: method="starknet_getNonce"
2025-01-01T05:51:48.063896Z DEBUG server: method="starknet_estimateFee"
2025-01-01T05:51:48.652324Z DEBUG server: method="starknet_addDeclareTransaction"
2025-01-01T05:51:48.752908Z  INFO pool: Transaction received. hash="0x29b190ab72220560f53e82e9b78d5f5720c0bf5ad62bb5a73997adc2fcb14aa"
2025-01-01T05:51:49.514750Z TRACE executor: Transaction resource usage. usage="steps: 3387 | memory holes: 32 | ec_op_builtin: 3 | pedersen_builtin: 16 | range_check_builtin: 65"
2025-01-01T05:51:49.893860Z  INFO katana::core::backend: Block mined. block_number=1 tx_count=1
2025-01-01T05:51:51.632321Z DEBUG server: method="starknet_getTransactionStatus"
2025-01-01T05:51:51.633337Z DEBUG server: method="starknet_getTransactionReceipt"
2025-01-01T05:51:51.635310Z DEBUG server: method="starknet_getClassHashAt"
2025-01-01T05:51:51.635892Z DEBUG server: method="starknet_getNonce"
2025-01-01T05:51:51.636646Z DEBUG server: method="starknet_estimateFee"
2025-01-01T05:51:51.660177Z DEBUG server: method="starknet_addInvokeTransaction"
2025-01-01T05:51:51.660336Z  INFO pool: Transaction received. hash="0x718cf01e9cb909a75e71057b001839a3fa300faf6127bb6e78345d9e8b872d"
2025-01-01T05:51:51.682489Z TRACE executor: Transaction resource usage. usage="steps: 8924 | memory holes: 56 | ec_op_builtin: 3 | pedersen_builtin: 37 | poseidon_builtin: 7 | range_check_builtin: 200"
2025-01-01T05:51:51.684674Z  INFO katana::core::backend: Block mined. block_number=2 tx_count=1
2025-01-01T05:51:54.164907Z DEBUG server: method="starknet_getTransactionStatus"
2025-01-01T05:51:54.165787Z DEBUG server: method="starknet_getTransactionReceipt"
2025-01-01T05:51:54.428801Z DEBUG server: method="dev_predeployedAccounts"
2025-01-01T05:51:54.429350Z DEBUG server: method="starknet_chainId"
2025-01-01T05:51:54.960783Z DEBUG server: method="starknet_getClass"
2025-01-01T05:51:54.960839Z DEBUG server: method="starknet_getClass"
2025-01-01T05:51:54.960939Z DEBUG server: method="starknet_getClass"
2025-01-01T05:51:54.960966Z DEBUG server: method="starknet_getClass"
2025-01-01T05:51:54.960985Z DEBUG server: method="starknet_getClass"
2025-01-01T05:51:54.961344Z DEBUG server: method="starknet_getNonce"
2025-01-01T05:51:54.961370Z DEBUG server: method="starknet_getNonce"
2025-01-01T05:51:54.961411Z DEBUG server: method="starknet_getNonce"
2025-01-01T05:51:54.961429Z DEBUG server: method="starknet_getNonce"
2025-01-01T05:51:54.961443Z DEBUG server: method="starknet_getNonce"
2025-01-01T05:51:54.967989Z DEBUG server: method="starknet_estimateFee"
2025-01-01T05:51:54.973595Z DEBUG server: method="starknet_estimateFee"
2025-01-01T05:51:54.978649Z DEBUG server: method="starknet_estimateFee"
2025-01-01T05:51:54.983303Z DEBUG server: method="starknet_estimateFee"
2025-01-01T05:51:54.997847Z DEBUG server: method="starknet_estimateFee"
2025-01-01T05:51:55.007605Z DEBUG server: method="starknet_addDeclareTransaction"
2025-01-01T05:51:55.013196Z DEBUG server: method="starknet_addDeclareTransaction"
2025-01-01T05:51:55.014823Z  INFO pool: Transaction received. hash="0x3496ed8396568366ba1e09e387f6a0fb8816d1878ff7e54377394d54de7a54c"Code/starknet-code/dojo-starter via 🅒 base 
➜ sozo migrate
2025-01-01T05:47:47.173185Z ERROR Subcommand{name="Migrate"}: sozo::cli: Provider health check failed during sozo migrate.
error: Unhealthy provider JsonRpcClient { transport: HttpTransport { client: Client { accepts: Accepts { gzip: true, brotli: true, deflate: true }, proxies: [Proxy(System({"http": http://127.0.0.1:33210, "https": http://127.0.0.1:33210}), None)], referer: true, default_headers: {"accept": "*/*"}, timeout: 30s }, url: Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("localhost")), port: Some(5050), path: "/", query: None, fragment: None }, headers: [] } }, please check your configuration.
关闭客户端与命令行代理
Code/starknet-code/dojo-starter via 🅒 base took 3.5s 
➜ unset https_proxy                  
unset http_proxy
Code/starknet-code/dojo-starter via 🅒 base took 3.5s 
➜ sozo migrate
 profile | chain_id | rpc_url                
---------+----------+------------------------
 dev     | KATANA   | http://localhost:5050/ 
🌍 World deployed at block 2 with txn hash: 0x00718cf01e9cb909a75e71057b001839a3fa300faf6127bb6e78345d9e8b872d
🗡️  Initializing 1 contracts...                  
IPFS credentials not found. Metadata upload skipped. To upload metadata, configure IPFS credentials in your profile config or environment variables: https://book.dojoengine.org/framework/world/metadata.
⛩️  Migration successful with world at address 0x0525177c8afe8680d7ad1da30ca183e482cfcd6404c1e09d83fd3fa2994fd4b8
dojo_dev.toml
world_address = "0x0525177c8afe8680d7ad1da30ca183e482cfcd6404c1e09d83fd3fa2994fd4b8"
Code/starknet-code/dojo-starter via 🅒 base 
➜ torii --world 0x0525177c8afe8680d7ad1da30ca183e482cfcd6404c1e09d83fd3fa2994fd4b8
2025-01-01T06:17:33.769805Z  INFO torii::relay::server: Relay peer id. peer_id=12D3KooWPu983NMc4J8jiRLxNNEcdodE8GSn65ckJ5MDvUNvspb1
2025-01-01T06:17:33.779795Z  INFO libp2p_swarm: local_peer_id=12D3KooWPu983NMc4J8jiRLxNNEcdodE8GSn65ckJ5MDvUNvspb1
2025-01-01T06:17:33.783130Z  INFO torii::cli: Starting torii endpoint. endpoint=127.0.0.1:8080
2025-01-01T06:17:33.783147Z  INFO torii::cli: Serving Graphql playground. endpoint=127.0.0.1:8080/graphql
2025-01-01T06:17:33.783150Z  INFO torii::cli: Serving World Explorer. url=https://worlds.dev/torii?url=127.0.0.1%3A8080%2Fgraphql
2025-01-01T06:17:33.783152Z  INFO torii::cli: Serving ERC artifacts at path path=/var/folders/6y/p7tl9yfj1p3cq9hv5z1fpfqh0000gn/T/.tmphAkzH2
2025-01-01T06:17:33.783865Z  INFO torii::relay::server: New listen address. address=/ip4/127.0.0.1/tcp/9090
2025-01-01T06:17:33.783945Z  INFO torii::relay::server: New listen address. address=/ip4/192.168.101.130/tcp/9090
2025-01-01T06:17:33.784000Z  INFO torii::relay::server: New listen address. address=/ip4/127.0.0.1/udp/9090/quic-v1
2025-01-01T06:17:33.784032Z  INFO torii::relay::server: New listen address. address=/ip4/192.168.101.130/udp/9090/quic-v1
2025-01-01T06:17:33.784681Z  INFO torii::relay::server: New listen address. address=/ip4/127.0.0.1/udp/9091/webrtc-direct/certhash/uEiBytYTBO8iWyiAJGgU0pHeQw7ECfH-udD9w4IgEJ9Kp4w
2025-01-01T06:17:33.784722Z  INFO torii::relay::server: New listen address. address=/ip4/192.168.101.130/udp/9091/webrtc-direct/certhash/uEiBytYTBO8iWyiAJGgU0pHeQw7ECfH-udD9w4IgEJ9Kp4w
2025-01-01T06:17:33.784801Z  INFO torii::relay::server: New listen address. address=/ip4/127.0.0.1/tcp/9092/ws
2025-01-01T06:17:33.784813Z  INFO torii::relay::server: New listen address. address=/ip4/192.168.101.130/tcp/9092/ws
2025-01-01T06:17:33.817216Z  INFO torii_core::engine: Processed block. block_number=2
2025-01-01T06:17:33.856743Z  INFO torii_core::processors::register_model: Registered model. namespace=dojo_starter name=Moves
2025-01-01T06:17:33.876042Z  INFO torii_core::processors::register_event: Registered event. namespace=dojo_starter name=Moved
2025-01-01T06:17:33.895447Z  INFO torii_core::processors::register_model: Registered model. namespace=dojo_starter name=Position
2025-01-01T06:17:33.915862Z  INFO torii_core::processors::register_model: Registered model. namespace=dojo_starter name=DirectionsAvailable
2025-01-01T06:17:33.915948Z  INFO torii_core::engine: Processed block. block_number=6
2025-01-01T06:17:33.915956Z  INFO torii_core::engine: Processed block. block_number=7
2025-01-01T06:17:33.915960Z  INFO torii_core::engine: Processed block. block_number=8
query DojoStarterMovesModels {
  dojoStarterMovesModels {
    totalCount
    edges {
      node {
        player
        remaining
        last_direction
        can_move
      }
    }
  }
}
query DojoStarterPositionModels {
  dojoStarterPositionModels {
    totalCount
    edges {
      node {
        player
        vec {
          x
          y
        }
      }
    }
  }
}
Code/starknet-code/dojo-starter via 🅒 base took 24.5s 
➜ sozo execute dojo_starter-actions spawn
Transaction hash: 0x07525e3d017399b4ed14a71cd710b510a0ebce22a78688f6b95abcc2c75c7aa1


Code/starknet-code/dojo-starter via 🅒 base 
➜ sozo execute dojo_starter-actions spawn
Transaction hash: 0x0424f539c3b84e22a612a59c3bfbdebffc76322c634b36a76fbf356a6a435518
 注意:此时可以看到 x、y 由 10 变为 20
注意:此时可以看到 x、y 由 10 变为 20
Code/starknet-code/dojo-starter via 🅒 base 
➜ sozo execute dojo_starter-actions move -c 0
Transaction hash: 0x03581ca2445eca52223d4710b3e6b95deb6dcd7fe705d49200eec3db49af330a

Code/starknet-code/dojo-starter via 🅒 base 
➜ sozo execute dojo_starter-actions move -c 1
Transaction hash: 0x033499b65f90bd88df5df59af256a276c58e67b28a7a1d595c0175afb4dc6065


Code/starknet-code/dojo-starter via 🅒 base took 3.6s 
➜ sozo test                                  
testing test(dojo_starter_unittest) dojo_starter v1.0.9 (/Users/qiaopengjun/Code/starknet-code/dojo-starter/Scarb.toml)
running 4 tests
test dojo_starter::models::tests::test_vec_is_equal ... ok (gas usage est.: 1300)
test dojo_starter::models::tests::test_vec_is_zero ... ok (gas usage est.: 1000)
test dojo_starter::tests::test_world::tests::test_world_test_set ... ok (gas usage est.: 12532285)
test dojo_starter::tests::test_world::tests::test_move ... ok (gas usage est.: 22057502)
test result: ok. 4 passed; 0 failed; 0 ignored; 0 filtered out;
 #[test]
    fn test_spawn() {
        let caller = starknet::contract_address_const::<0x0>();
        let ndef = namespace_def();
        let mut world = spawn_test_world([ndef].span());
        world.sync_perms_and_inits(contract_defs());
        let (contract_address, _) = world.dns(@"actions").unwrap();
        let actions_system = IActionsDispatcher {contract_address};
        actions_system.spawn();
        let moves: Moves = world.read_model(caller);
        assert(moves.remaining == 100, 'initial moves wrong');
        assert(moves.last_direction == Direction::None, 'initial direction wrong');
        let position: Position = world.read_model(caller);
        assert(position.vec.x == 10 && position.vec.y == 10, 'initial position wrong');
        actions_system.spawn();
        let position: Position = world.read_model(caller);
        assert(position.vec.x == 20 && position.vec.y == 20, 'x y coordinate not updated');
    }Code/starknet-code/dojo-starter via 🅒 base 
➜ sozo test                                  
testing test(dojo_starter_unittest) dojo_starter v1.0.9 (/Users/qiaopengjun/Code/starknet-code/dojo-starter/Scarb.toml)
running 5 tests
test dojo_starter::models::tests::test_vec_is_zero ... ok (gas usage est.: 1000)
test dojo_starter::models::tests::test_vec_is_equal ... ok (gas usage est.: 1300)
test dojo_starter::tests::test_world::tests::test_world_test_set ... ok (gas usage est.: 12532285)
test dojo_starter::tests::test_world::tests::test_spawn ... ok (gas usage est.: 18893689)
test dojo_starter::tests::test_world::tests::test_move ... ok (gas usage est.: 22057502)
test result: ok. 5 passed; 0 failed; 0 ignored; 0 filtered out;
建议:面向测试开发并编写测试用例来保证 Dojo 合约的正确性。
 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!