diff --git a/mover/minhnd410/README.md b/mover/minhnd410/README.md new file mode 100644 index 00000000..e96d4198 --- /dev/null +++ b/mover/minhnd410/README.md @@ -0,0 +1,44 @@ +## Basic Information +- Sui Wallet Address: `0xf6429b3bfe3fa36cf6a56695f2fe9ad071dc03ed47d5178bf7d740711da1c442` +- Github: `minhnd410` + +## Personal Introduction +- Work Experience: `8` +- Tech Stack: `C#`, `Javascript` , ... +- Nearly 8 years of experience in web application development and driving digital transformation for small and medium-sized enterprises in Vietnam, I have successfully deployed and operated numerous products using my preferred programming stack: C#, .NET, SQL Server, and various JavaScript frameworks on Azure Cloud. I believe that Move is a promising programming language that can help me to enter the blockchain world. I am excited to learn more about it. +- Contact: telegram `minhnd410` + +## Tasks + +### 01 hello move +- [x] Sui CLI Version: sui 1.39.3-homebrew +- [x] Sui Wallet Screenshot: [images/task1-sui-wallet.png](./images/task1-sui-wallet.png) +- [x] Package ID: `0x6e86b0b8422822c6990455df426b165f6acc78707fe1d75a4f7884eb58ef891b` +- [x] Package ID's [images/task1-package-id.png](./images/task1-package-id.png) + +### 02 move coin +- [x] `My Coin` Package ID: `0xe59be9ecc6460b70eac6b8c207ae2d7453901c9b017e3ef88a767548450d6db0` +- [x] `Faucet Coin` Package ID: `0xe47b867c5383eb363abdb5d7762f1b64641c37e9b24c295fbba49f56e719671f` +- [x] Transfer `My Coin` hash: `3BBYHkJWrG4CpKp3dXBEMPBDyrYPuuRwoqWtfzew8MzM` +- [x] `Faucet Coin` address 1 mint hash: `AcMLxT8rpWusZp6eLD3fXNezYGGqyLaMqJ4EYEXEL6yQ` +- [x] `Faucet Coin` address 2 mint hash: `FPEpyALHSZZSvCsKsbu6s4R4R5MzARMXdvCdAhf3hHWu` + +### 03 move nft +- [x] NFT Package ID: `0x51349746bf9269633ae178c868fb24822f6433a2c33d912371b79afb7d86625b` +- [x] NFT Object ID: `0x8f3768b0d74b7625e66ddce7518c56515b90005547b618b91b96ed61b7f38f9e` +- [x] Transfer NFT hash: `BuK71qhfa2svJyk3X9LUohmduXFJ3ddzfw5u4rkHrK3y` +- [x] NFT's Screenshot from Explorer: [images/task3-nft.png](./images/task3-nft.png) + +### 04 move game +- [x] Game Package ID: `0x94083fe279e3e43eea4eaed795741b19f912f0dd762c4540b68f2f9f3e7d1d8c` +- [x] Deposit Coin Hash: `B1pxtAXVXQXx9ZovxSfZ4KtS9nVsdKshUTQmVAUnid41` +- [x] Withdraw Coin Hash: `CQpraQptnpd4fRH3RbfWZJJotS3itVAT7YCzos2emd2F` +- [x] Play Game Hash: `9TJariQyfuP474SNTPpjmvLjZf5DiDHZJDa5mPM7UY5j` + +### 05 move swap +- [ ] Swap Package ID: +- [ ] Call Swap Coin A -> Coin B hash: +- [ ] Call Swap Coin B -> Coin A hash: + +### 06 dapp-kit SDK PTB +- [ ] Save Hash: diff --git a/mover/minhnd410/code/README.md b/mover/minhnd410/code/README.md new file mode 100644 index 00000000..434f1d0a --- /dev/null +++ b/mover/minhnd410/code/README.md @@ -0,0 +1,27 @@ +## Command used + +```bash +# Create new package +sui move new task1 + +# Build the project +sui move build + +# Run the test +sui move test + +# Import seed phrase from sui wallet +sui keytool import ed25519 "m/44'/784'/0'/0'/0'" + +# Check if address is active +sui client addresses + +# Switch to the desired address +sui client switch --address + +# Request faucet +sui client faucet --address
+ +# Publish the package +sui client publish +``` \ No newline at end of file diff --git a/mover/minhnd410/code/task1/.gitignore b/mover/minhnd410/code/task1/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/minhnd410/code/task1/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/minhnd410/code/task1/Move.lock b/mover/minhnd410/code/task1/Move.lock new file mode 100644 index 00000000..704b7709 --- /dev/null +++ b/mover/minhnd410/code/task1/Move.lock @@ -0,0 +1,34 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "8B7DC3EDF1D81F9E2D46D8251E70F4B8D7097878F02438454C30AEF9F05D81D0" +deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" +dependencies = [ + { id = "Sui", name = "Sui" }, +] + +[[move.package]] +id = "MoveStdlib" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/move-stdlib" } + +[[move.package]] +id = "Sui" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/sui-framework" } + +dependencies = [ + { id = "MoveStdlib", name = "MoveStdlib" }, +] + +[move.toolchain-version] +compiler-version = "1.39.3" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0x6e86b0b8422822c6990455df426b165f6acc78707fe1d75a4f7884eb58ef891b" +latest-published-id = "0x6e86b0b8422822c6990455df426b165f6acc78707fe1d75a4f7884eb58ef891b" +published-version = "1" diff --git a/mover/minhnd410/code/task1/Move.toml b/mover/minhnd410/code/task1/Move.toml new file mode 100644 index 00000000..f99a76a8 --- /dev/null +++ b/mover/minhnd410/code/task1/Move.toml @@ -0,0 +1,37 @@ +[package] +name = "hello_move" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move +# license = "" # e.g., "MIT", "GPL", "Apache 2.0" +# authors = ["..."] # e.g., ["Joe Smith (joesmith@noemail.com)", "John Snow (johnsnow@noemail.com)"] + +[dependencies] +Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" } + +# For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`. +# Revision can be a branch, a tag, and a commit hash. +# MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" } + +# For local dependencies use `local = path`. Path is relative to the package root +# Local = { local = "../path/to" } + +# To resolve a version conflict and force a specific version for dependency +# override use `override = true` +# Override = { local = "../conflicting/version", override = true } + +[addresses] +hello_move = "0x0" + +# Named addresses will be accessible in Move as `@name`. They're also exported: +# for example, `std = "0x1"` is exported by the Standard Library. +# alice = "0xA11CE" + +[dev-dependencies] +# The dev-dependencies section allows overriding dependencies for `--test` and +# `--dev` modes. You can introduce test-only dependencies here. +# Local = { local = "../path/to/dev-build" } + +[dev-addresses] +# The dev-addresses section allows overwriting named addresses for the `--test` +# and `--dev` modes. +# alice = "0xB0B" + diff --git a/mover/minhnd410/code/task1/README.md b/mover/minhnd410/code/task1/README.md new file mode 100644 index 00000000..5d4bbb68 --- /dev/null +++ b/mover/minhnd410/code/task1/README.md @@ -0,0 +1,9 @@ +## Command used + +```bash +# Build the project +sui move build + +# Run the test +sui move test +``` \ No newline at end of file diff --git a/mover/minhnd410/code/task1/sources/hello_move.move b/mover/minhnd410/code/task1/sources/hello_move.move new file mode 100644 index 00000000..89c09ae6 --- /dev/null +++ b/mover/minhnd410/code/task1/sources/hello_move.move @@ -0,0 +1,44 @@ +module hello_move::mover; + +use std::string::{Self, String}; + +public struct Mover has key, store { + id: UID, + github_id: String, +} + +fun init(ctx: &mut TxContext) { + let mover = Mover { + id: object::new(ctx), + github_id: string::utf8(b"minhnd410"), + }; + + transfer::transfer(mover, ctx.sender()); +} + +public fun github_id(self: &Mover): String { + self.github_id +} + +#[test] +fun test_mover() { + use sui::test_scenario; + + let admin = @0xAD; + + let mut scenario = test_scenario::begin(admin); + { + init(scenario.ctx()); + }; + + scenario.next_tx(admin); + { + let mover = scenario.take_from_sender(); + // Verify number of created swords + assert!(mover.github_id() == string::utf8(b"minhnd410"), 1); + // Return the Forge object to the object pool + scenario.return_to_sender(mover); + }; + + scenario.end(); +} \ No newline at end of file diff --git a/mover/minhnd410/code/task1/tests/hello_move_tests.move b/mover/minhnd410/code/task1/tests/hello_move_tests.move new file mode 100644 index 00000000..7798d8dd --- /dev/null +++ b/mover/minhnd410/code/task1/tests/hello_move_tests.move @@ -0,0 +1,18 @@ +/* +#[test_only] +module hello_move::hello_move_tests; +// uncomment this line to import the module +// use hello_move::hello_move; + +const ENotImplemented: u64 = 0; + +#[test] +fun test_hello_move() { + // pass +} + +#[test, expected_failure(abort_code = ::hello_move::hello_move_tests::ENotImplemented)] +fun test_hello_move_fail() { + abort ENotImplemented +} +*/ diff --git a/mover/minhnd410/code/task2/README.md b/mover/minhnd410/code/task2/README.md new file mode 100644 index 00000000..a81d0fe0 --- /dev/null +++ b/mover/minhnd410/code/task2/README.md @@ -0,0 +1,7 @@ +```bash +# Mint coin +sui client call --function mint --module minhnd410 --package 0xe59be9ecc6460b70eac6b8c207ae2d7453901c9b017e3ef88a767548450d6db0 --args 0xb36752efb2c95063557a924eb89385d29ea2adc08a69fd68723556a7637f423f 1000000 0xf6429b3bfe3fa36cf6a56695f2fe9ad071dc03ed47d5178bf7d740711da1c442 + +sui client call --function mint --module minhnd410_Faucet --package 0xe47b867c5383eb363abdb5d7762f1b64641c37e9b24c295fbba49f56e719671f --args 0x126bdf130cc2c2aafbc1bb98de6c2c406d19421b780f751b567d5003cd4dedd8 1000000 0xa1646edd2b1acb5a3da109896d7e2aaee0cc9ac0ee3882c40f62c71bf1da18e2 + +``` \ No newline at end of file diff --git a/mover/minhnd410/code/task2/move_coin/.gitignore b/mover/minhnd410/code/task2/move_coin/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/minhnd410/code/task2/move_coin/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/minhnd410/code/task2/move_coin/Move.lock b/mover/minhnd410/code/task2/move_coin/Move.lock new file mode 100644 index 00000000..48307bca --- /dev/null +++ b/mover/minhnd410/code/task2/move_coin/Move.lock @@ -0,0 +1,34 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "8EB223C8F40D0F546D3CD1F4773472F9D95459A9E8E5F61FE9A5E8BE25350372" +deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" +dependencies = [ + { id = "Sui", name = "Sui" }, +] + +[[move.package]] +id = "MoveStdlib" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/move-stdlib" } + +[[move.package]] +id = "Sui" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/sui-framework" } + +dependencies = [ + { id = "MoveStdlib", name = "MoveStdlib" }, +] + +[move.toolchain-version] +compiler-version = "1.39.3" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0xe59be9ecc6460b70eac6b8c207ae2d7453901c9b017e3ef88a767548450d6db0" +latest-published-id = "0xe59be9ecc6460b70eac6b8c207ae2d7453901c9b017e3ef88a767548450d6db0" +published-version = "1" diff --git a/mover/minhnd410/code/task2/move_coin/Move.toml b/mover/minhnd410/code/task2/move_coin/Move.toml new file mode 100644 index 00000000..a3f7d1e7 --- /dev/null +++ b/mover/minhnd410/code/task2/move_coin/Move.toml @@ -0,0 +1,37 @@ +[package] +name = "move_coin" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move +# license = "" # e.g., "MIT", "GPL", "Apache 2.0" +# authors = ["..."] # e.g., ["Joe Smith (joesmith@noemail.com)", "John Snow (johnsnow@noemail.com)"] + +[dependencies] +Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" } + +# For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`. +# Revision can be a branch, a tag, and a commit hash. +# MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" } + +# For local dependencies use `local = path`. Path is relative to the package root +# Local = { local = "../path/to" } + +# To resolve a version conflict and force a specific version for dependency +# override use `override = true` +# Override = { local = "../conflicting/version", override = true } + +[addresses] +move_coin = "0x0" + +# Named addresses will be accessible in Move as `@name`. They're also exported: +# for example, `std = "0x1"` is exported by the Standard Library. +# alice = "0xA11CE" + +[dev-dependencies] +# The dev-dependencies section allows overriding dependencies for `--test` and +# `--dev` modes. You can introduce test-only dependencies here. +# Local = { local = "../path/to/dev-build" } + +[dev-addresses] +# The dev-addresses section allows overwriting named addresses for the `--test` +# and `--dev` modes. +# alice = "0xB0B" + diff --git a/mover/minhnd410/code/task2/move_coin/sources/minhnd410.move b/mover/minhnd410/code/task2/move_coin/sources/minhnd410.move new file mode 100644 index 00000000..079746ca --- /dev/null +++ b/mover/minhnd410/code/task2/move_coin/sources/minhnd410.move @@ -0,0 +1,31 @@ +module move_coin::minhnd410; + +use sui::coin::{Self, TreasuryCap}; +use sui::url::{new_unsafe}; + +public struct MINHND410 has drop {} + +fun init(witness: MINHND410, ctx: &mut TxContext) { + let token_url = new_unsafe(std::ascii::string(b"https://strapi-dev.scand.app/uploads/sui_c07df05f00.png")); + let (treasury, metadata) = coin::create_currency( + witness, + 6, + b"MINHND410", + b"minhnd410 coin", + b"task 2 - coin", + option::some(token_url), + ctx, + ); + transfer::public_freeze_object(metadata); + transfer::public_transfer(treasury, ctx.sender()) +} + +public fun mint( + treasury_cap: &mut TreasuryCap, + amount: u64, + recipient: address, + ctx: &mut TxContext, +) { + let coin = coin::mint(treasury_cap, amount, ctx); + transfer::public_transfer(coin, recipient) +} \ No newline at end of file diff --git a/mover/minhnd410/code/task2/move_coin/tests/move_coin_tests.move b/mover/minhnd410/code/task2/move_coin/tests/move_coin_tests.move new file mode 100644 index 00000000..1a0af724 --- /dev/null +++ b/mover/minhnd410/code/task2/move_coin/tests/move_coin_tests.move @@ -0,0 +1,18 @@ +/* +#[test_only] +module move_coin::move_coin_tests; +// uncomment this line to import the module +// use move_coin::move_coin; + +const ENotImplemented: u64 = 0; + +#[test] +fun test_move_coin() { + // pass +} + +#[test, expected_failure(abort_code = ::move_coin::move_coin_tests::ENotImplemented)] +fun test_move_coin_fail() { + abort ENotImplemented +} +*/ diff --git a/mover/minhnd410/code/task2/move_faucet_coin/.gitignore b/mover/minhnd410/code/task2/move_faucet_coin/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/minhnd410/code/task2/move_faucet_coin/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/minhnd410/code/task2/move_faucet_coin/Move.lock b/mover/minhnd410/code/task2/move_faucet_coin/Move.lock new file mode 100644 index 00000000..e798bdf6 --- /dev/null +++ b/mover/minhnd410/code/task2/move_faucet_coin/Move.lock @@ -0,0 +1,34 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "ED8E02F3BAA177E30ED58083BAD0B87A059B6412A5ADE8A9643EB728516A7C30" +deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" +dependencies = [ + { id = "Sui", name = "Sui" }, +] + +[[move.package]] +id = "MoveStdlib" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/move-stdlib" } + +[[move.package]] +id = "Sui" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/sui-framework" } + +dependencies = [ + { id = "MoveStdlib", name = "MoveStdlib" }, +] + +[move.toolchain-version] +compiler-version = "1.39.3" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0xe47b867c5383eb363abdb5d7762f1b64641c37e9b24c295fbba49f56e719671f" +latest-published-id = "0xe47b867c5383eb363abdb5d7762f1b64641c37e9b24c295fbba49f56e719671f" +published-version = "1" diff --git a/mover/minhnd410/code/task2/move_faucet_coin/Move.toml b/mover/minhnd410/code/task2/move_faucet_coin/Move.toml new file mode 100644 index 00000000..303fb41c --- /dev/null +++ b/mover/minhnd410/code/task2/move_faucet_coin/Move.toml @@ -0,0 +1,37 @@ +[package] +name = "move_faucet_coin" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move +# license = "" # e.g., "MIT", "GPL", "Apache 2.0" +# authors = ["..."] # e.g., ["Joe Smith (joesmith@noemail.com)", "John Snow (johnsnow@noemail.com)"] + +[dependencies] +Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" } + +# For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`. +# Revision can be a branch, a tag, and a commit hash. +# MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" } + +# For local dependencies use `local = path`. Path is relative to the package root +# Local = { local = "../path/to" } + +# To resolve a version conflict and force a specific version for dependency +# override use `override = true` +# Override = { local = "../conflicting/version", override = true } + +[addresses] +move_faucet_coin = "0x0" + +# Named addresses will be accessible in Move as `@name`. They're also exported: +# for example, `std = "0x1"` is exported by the Standard Library. +# alice = "0xA11CE" + +[dev-dependencies] +# The dev-dependencies section allows overriding dependencies for `--test` and +# `--dev` modes. You can introduce test-only dependencies here. +# Local = { local = "../path/to/dev-build" } + +[dev-addresses] +# The dev-addresses section allows overwriting named addresses for the `--test` +# and `--dev` modes. +# alice = "0xB0B" + diff --git a/mover/minhnd410/code/task2/move_faucet_coin/sources/move_faucet_coin.move b/mover/minhnd410/code/task2/move_faucet_coin/sources/move_faucet_coin.move new file mode 100644 index 00000000..cfee2f25 --- /dev/null +++ b/mover/minhnd410/code/task2/move_faucet_coin/sources/move_faucet_coin.move @@ -0,0 +1,31 @@ +module move_faucet_coin::minhnd410_Faucet; + +use sui::coin::{Self, TreasuryCap}; +use sui::url::{new_unsafe}; + +public struct MINHND410_FAUCET has drop {} + +fun init(witness: MINHND410_FAUCET, ctx: &mut TxContext) { + let token_url = new_unsafe(std::ascii::string(b"https://strapi-dev.scand.app/uploads/sui_c07df05f00.png")); + let (treasury, metadata) = coin::create_currency( + witness, + 6, + b"MINHND410_FAUCET", + b"minhnd410 faucet coin", + b"task 2 - faucet coin", + option::some(token_url), + ctx, + ); + transfer::public_freeze_object(metadata); + transfer::public_share_object(treasury) +} + +public fun mint( + treasury_cap: &mut TreasuryCap, + amount: u64, + recipient: address, + ctx: &mut TxContext, +) { + let coin = coin::mint(treasury_cap, amount, ctx); + transfer::public_transfer(coin, recipient) +} \ No newline at end of file diff --git a/mover/minhnd410/code/task2/move_faucet_coin/tests/move_faucet_coin_tests.move b/mover/minhnd410/code/task2/move_faucet_coin/tests/move_faucet_coin_tests.move new file mode 100644 index 00000000..b5fd7bbd --- /dev/null +++ b/mover/minhnd410/code/task2/move_faucet_coin/tests/move_faucet_coin_tests.move @@ -0,0 +1,18 @@ +/* +#[test_only] +module move_faucet_coin::move_faucet_coin_tests; +// uncomment this line to import the module +// use move_faucet_coin::move_faucet_coin; + +const ENotImplemented: u64 = 0; + +#[test] +fun test_move_faucet_coin() { + // pass +} + +#[test, expected_failure(abort_code = ::move_faucet_coin::move_faucet_coin_tests::ENotImplemented)] +fun test_move_faucet_coin_fail() { + abort ENotImplemented +} +*/ diff --git a/mover/minhnd410/code/task3/move_nft/.gitignore b/mover/minhnd410/code/task3/move_nft/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/minhnd410/code/task3/move_nft/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/minhnd410/code/task3/move_nft/Move.lock b/mover/minhnd410/code/task3/move_nft/Move.lock new file mode 100644 index 00000000..e6ef401f --- /dev/null +++ b/mover/minhnd410/code/task3/move_nft/Move.lock @@ -0,0 +1,34 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "4540D330C6E846CAE6F9BE6749EE389FEBF0A14ECFBE748ED332A79FDCAF28EE" +deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082" +dependencies = [ + { id = "Sui", name = "Sui" }, +] + +[[move.package]] +id = "MoveStdlib" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/move-stdlib" } + +[[move.package]] +id = "Sui" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/sui-framework" } + +dependencies = [ + { id = "MoveStdlib", name = "MoveStdlib" }, +] + +[move.toolchain-version] +compiler-version = "1.39.3" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0x51349746bf9269633ae178c868fb24822f6433a2c33d912371b79afb7d86625b" +latest-published-id = "0x51349746bf9269633ae178c868fb24822f6433a2c33d912371b79afb7d86625b" +published-version = "1" diff --git a/mover/minhnd410/code/task3/move_nft/Move.toml b/mover/minhnd410/code/task3/move_nft/Move.toml new file mode 100644 index 00000000..eb96b74d --- /dev/null +++ b/mover/minhnd410/code/task3/move_nft/Move.toml @@ -0,0 +1,37 @@ +[package] +name = "move_nft" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move +# license = "" # e.g., "MIT", "GPL", "Apache 2.0" +# authors = ["..."] # e.g., ["Joe Smith (joesmith@noemail.com)", "John Snow (johnsnow@noemail.com)"] + +[dependencies] +Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" } + +# For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`. +# Revision can be a branch, a tag, and a commit hash. +# MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" } + +# For local dependencies use `local = path`. Path is relative to the package root +# Local = { local = "../path/to" } + +# To resolve a version conflict and force a specific version for dependency +# override use `override = true` +# Override = { local = "../conflicting/version", override = true } + +[addresses] +move_nft = "0x0" + +# Named addresses will be accessible in Move as `@name`. They're also exported: +# for example, `std = "0x1"` is exported by the Standard Library. +# alice = "0xA11CE" + +[dev-dependencies] +# The dev-dependencies section allows overriding dependencies for `--test` and +# `--dev` modes. You can introduce test-only dependencies here. +# Local = { local = "../path/to/dev-build" } + +[dev-addresses] +# The dev-addresses section allows overwriting named addresses for the `--test` +# and `--dev` modes. +# alice = "0xB0B" + diff --git a/mover/minhnd410/code/task3/move_nft/README.md b/mover/minhnd410/code/task3/move_nft/README.md new file mode 100644 index 00000000..c4ded2ee --- /dev/null +++ b/mover/minhnd410/code/task3/move_nft/README.md @@ -0,0 +1,6 @@ +```bash +sui client call --function mint_to_sender --module minhnd410_nft --package 0x51349746bf9269633ae178c868fb24822f6433a2c33d912371b79afb7d86625b --args "minhnd410 nft" "task 3 move_nft" + +sui client call --function transfer --module minhnd410_nft --package 0x51349746bf9269633ae178c868fb24822f6433a2c33d912371b79afb7d86625b --args 0x8f3768b0d74b7625e66ddce7518c56515b90005547b618b91b96ed61b7f38f9e 0xa9ddd77d41119bdcbab0f5c4d18bf15e65034607afc5a296865f640e0d33d958 + +``` \ No newline at end of file diff --git a/mover/minhnd410/code/task3/move_nft/sources/move_nft.move b/mover/minhnd410/code/task3/move_nft/sources/move_nft.move new file mode 100644 index 00000000..88a6d435 --- /dev/null +++ b/mover/minhnd410/code/task3/move_nft/sources/move_nft.move @@ -0,0 +1,92 @@ +module move_nft::minhnd410_nft; + +use std::string; +use sui::{event, url::{Self, Url}}; + +/// An example NFT that can be minted by anybody +public struct Minhnd410NFT has key, store { + id: UID, + /// Name for the token + name: string::String, + /// Description of the token + description: string::String, + /// URL for the token + url: Url, + // TODO: allow custom attributes +} + +// ===== Events ===== + +public struct Minhnd410NFTMinted has copy, drop { + // The Object ID of the NFT + object_id: ID, + // The creator of the NFT + creator: address, + // The name of the NFT + name: string::String, +} + +// ===== Public view functions ===== + +/// Get the NFT's `name` +public fun name(nft: &Minhnd410NFT): &string::String { + &nft.name +} + +/// Get the NFT's `description` +public fun description(nft: &Minhnd410NFT): &string::String { + &nft.description +} + +/// Get the NFT's `url` +public fun url(nft: &Minhnd410NFT): &Url { + &nft.url +} + +// ===== Entrypoints ===== + +#[allow(lint(self_transfer))] +/// Create a new devnet_nft +public fun mint_to_sender( + name: vector, + description: vector, + ctx: &mut TxContext, +) { + let url: vector = b"https://avatars.githubusercontent.com/u/91967823"; + + let sender = ctx.sender(); + let nft = Minhnd410NFT { + id: object::new(ctx), + name: string::utf8(name), + description: string::utf8(description), + url: url::new_unsafe_from_bytes(url), + }; + + event::emit(Minhnd410NFTMinted { + object_id: object::id(&nft), + creator: sender, + name: nft.name, + }); + + transfer::public_transfer(nft, sender); +} + +/// Transfer `nft` to `recipient` +public fun transfer(nft: Minhnd410NFT, recipient: address, _: &mut TxContext) { + transfer::public_transfer(nft, recipient) +} + +/// Update the `description` of `nft` to `new_description` +public fun update_description( + nft: &mut Minhnd410NFT, + new_description: vector, + _: &mut TxContext, +) { + nft.description = string::utf8(new_description) +} + +/// Permanently delete `nft` +public fun burn(nft: Minhnd410NFT, _: &mut TxContext) { + let Minhnd410NFT { id, name: _, description: _, url: _ } = nft; + id.delete() +} \ No newline at end of file diff --git a/mover/minhnd410/code/task3/move_nft/tests/move_nft_tests.move b/mover/minhnd410/code/task3/move_nft/tests/move_nft_tests.move new file mode 100644 index 00000000..d35681af --- /dev/null +++ b/mover/minhnd410/code/task3/move_nft/tests/move_nft_tests.move @@ -0,0 +1,18 @@ +/* +#[test_only] +module move_nft::move_nft_tests; +// uncomment this line to import the module +// use move_nft::move_nft; + +const ENotImplemented: u64 = 0; + +#[test] +fun test_move_nft() { + // pass +} + +#[test, expected_failure(abort_code = ::move_nft::move_nft_tests::ENotImplemented)] +fun test_move_nft_fail() { + abort ENotImplemented +} +*/ diff --git a/mover/minhnd410/code/task4/move_game/.gitignore b/mover/minhnd410/code/task4/move_game/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/minhnd410/code/task4/move_game/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/minhnd410/code/task4/move_game/Move.lock b/mover/minhnd410/code/task4/move_game/Move.lock new file mode 100644 index 00000000..6ba732bd --- /dev/null +++ b/mover/minhnd410/code/task4/move_game/Move.lock @@ -0,0 +1,43 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "06815CB8870336007D565EE998964C8AB159DF121CC282821AE3A7448C473044" +deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600" +dependencies = [ + { id = "Sui", name = "Sui" }, + { id = "move_faucet_coin", name = "move_faucet_coin" }, +] + +[[move.package]] +id = "MoveStdlib" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/move-stdlib" } + +[[move.package]] +id = "Sui" +source = { git = "https://github.com/MystenLabs/sui.git", rev = "framework/testnet", subdir = "crates/sui-framework/packages/sui-framework" } + +dependencies = [ + { id = "MoveStdlib", name = "MoveStdlib" }, +] + +[[move.package]] +id = "move_faucet_coin" +source = { local = "../../task2/move_faucet_coin" } + +dependencies = [ + { id = "Sui", name = "Sui" }, +] + +[move.toolchain-version] +compiler-version = "1.39.3" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0x94083fe279e3e43eea4eaed795741b19f912f0dd762c4540b68f2f9f3e7d1d8c" +latest-published-id = "0x94083fe279e3e43eea4eaed795741b19f912f0dd762c4540b68f2f9f3e7d1d8c" +published-version = "1" diff --git a/mover/minhnd410/code/task4/move_game/Move.toml b/mover/minhnd410/code/task4/move_game/Move.toml new file mode 100644 index 00000000..ecdfba53 --- /dev/null +++ b/mover/minhnd410/code/task4/move_game/Move.toml @@ -0,0 +1,38 @@ +[package] +name = "move_game" +edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move +# license = "" # e.g., "MIT", "GPL", "Apache 2.0" +# authors = ["..."] # e.g., ["Joe Smith (joesmith@noemail.com)", "John Snow (johnsnow@noemail.com)"] + +[dependencies] +Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" } + +# For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`. +# Revision can be a branch, a tag, and a commit hash. +# MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" } + +# For local dependencies use `local = path`. Path is relative to the package root +# Local = { local = "../path/to" } +move_faucet_coin = { local = "../../task2/move_faucet_coin" } + +# To resolve a version conflict and force a specific version for dependency +# override use `override = true` +# Override = { local = "../conflicting/version", override = true } + +[addresses] +move_game = "0x0" + +# Named addresses will be accessible in Move as `@name`. They're also exported: +# for example, `std = "0x1"` is exported by the Standard Library. +# alice = "0xA11CE" + +[dev-dependencies] +# The dev-dependencies section allows overriding dependencies for `--test` and +# `--dev` modes. You can introduce test-only dependencies here. +# Local = { local = "../path/to/dev-build" } + +[dev-addresses] +# The dev-addresses section allows overwriting named addresses for the `--test` +# and `--dev` modes. +# alice = "0xB0B" + diff --git a/mover/minhnd410/code/task4/move_game/sources/fund_pool.move b/mover/minhnd410/code/task4/move_game/sources/fund_pool.move new file mode 100644 index 00000000..43d00692 --- /dev/null +++ b/mover/minhnd410/code/task4/move_game/sources/fund_pool.move @@ -0,0 +1,90 @@ +module move_game::fund_pool; + +use sui::balance::{Balance}; +use sui::coin::{Self, Coin}; +use sui::package::{Self}; + +use move_faucet_coin::minhnd410_Faucet::{MINHND410_FAUCET}; + +const ECallerNotOwner: u64 = 0; +const EInsufficientBalance: u64 = 1; + +public struct FundPool has key { + id: UID, + balance: Balance, + owner: address, + public_key: vector, + github_id: vector, +} + +public struct FundPoolCap has key { + id: UID +} + +public struct FUND_POOL has drop {} + +fun init(otw: FUND_POOL, ctx: &mut TxContext) { + package::claim_and_keep(otw, ctx); + + let fund_pool_cap = FundPoolCap { + id: object::new(ctx) + }; + + transfer::transfer(fund_pool_cap, ctx.sender()); +} + +public fun initialize_fund_pool(fund_pool_cap: FundPoolCap, coin: Coin, public_key: vector, ctx: &mut TxContext) { + assert!(coin.value() > 0, EInsufficientBalance); + + let fund_pool = FundPool { + id: object::new(ctx), + balance: coin.into_balance(), + owner: ctx.sender(), + public_key, + github_id: b"minhnd410" + }; + + let FundPoolCap { id } = fund_pool_cap; + object::delete(id); + + transfer::share_object(fund_pool); +} + +public fun deposit(fund_pool: &mut FundPool, coin: Coin, _: &mut TxContext) { + coin::put(&mut fund_pool.balance, coin) +} + +public fun withdraw(fund_pool: &mut FundPool, ctx: &mut TxContext) { + assert!(ctx.sender() == fund_pool.owner(), ECallerNotOwner); + + let total_balance = balance(fund_pool); + let coin = coin::take(&mut fund_pool.balance, total_balance, ctx); + transfer::public_transfer(coin, fund_pool.owner()); +} + +// --------------- Mutable References --------------- + +public(package) fun borrow_balance_mut(fund_pool: &mut FundPool): &mut Balance { + &mut fund_pool.balance +} + +public(package) fun borrow_mut(fund_pool: &mut FundPool): &mut UID { + &mut fund_pool.id +} + +// --------------- Read-only References --------------- +public(package) fun borrow(fund_pool: &FundPool): &UID { + &fund_pool.id +} + +public fun public_key(fund_pool: &FundPool): vector { + fund_pool.public_key +} + +public fun owner(fund_pool: &FundPool): address { + fund_pool.owner +} + +public fun balance(fund_pool: &FundPool): u64 { + fund_pool.balance.value() +} \ No newline at end of file diff --git a/mover/minhnd410/code/task4/move_game/sources/game_counter.move b/mover/minhnd410/code/task4/move_game/sources/game_counter.move new file mode 100644 index 00000000..6807ceec --- /dev/null +++ b/mover/minhnd410/code/task4/move_game/sources/game_counter.move @@ -0,0 +1,39 @@ +module move_game::game_counter; + +use sui::bcs::{Self}; + +public struct GameCounter has key { + id: UID, + github_id: vector, + count: u64, +} + +public fun mint(ctx: &mut TxContext): GameCounter { + GameCounter { + id: object::new(ctx), + count: 0, + github_id: b"minhnd410" + } +} + +public fun transfer_to_sender(counter: GameCounter, ctx: &mut TxContext) { + transfer::transfer(counter, tx_context::sender(ctx)); +} + +public fun get_vrf_input_and_increment(self: &mut GameCounter): vector { + let mut vrf_input = object::id_bytes(self); + let count_to_bytes = bcs::to_bytes(&count(self)); + vrf_input.append(count_to_bytes); + self.increment(); + vrf_input +} + +public fun count(self: &GameCounter): u64 { + self.count +} + +// === Internal === + +fun increment(self: &mut GameCounter) { + self.count = self.count + 1; +} diff --git a/mover/minhnd410/code/task4/move_game/sources/game_play.move b/mover/minhnd410/code/task4/move_game/sources/game_play.move new file mode 100644 index 00000000..baa44fb2 --- /dev/null +++ b/mover/minhnd410/code/task4/move_game/sources/game_play.move @@ -0,0 +1,118 @@ +module move_game::game_play; + +use sui::coin::{Self, Coin}; +use sui::balance::Balance; +use sui::bls12381::bls12381_min_pk_verify; +use sui::hash::{blake2b256}; +use std::string::String; +use sui::dynamic_object_field::{Self as dof}; + +use move_game::fund_pool::FundPool; +use move_game::game_counter::GameCounter; +use move_faucet_coin::minhnd410_Faucet::{MINHND410_FAUCET}; + +const HEADS: vector = b"H"; +const TAILS: vector = b"T"; + +const EInvalidBlsSig: u64 = 2; +const EInvalidGuess: u64 = 4; +const EInsufficientFundPoolBalance: u64 = 5; +const EGameDoesNotExist: u64 = 6; + +const PLAYER_WON_STATE: u8 = 1; +const PLAYER_LOSE_STATE: u8 = 2; + +public struct Game has key, store { + id: UID, + guess_placed_epoch: u64, + total_stake: Balance, + guess: String, + player: address, + vrf_input: vector, + github_id: vector, +} + +public fun start_game(guess: String, counter: &mut GameCounter, coin: Coin, fund_pool: &mut FundPool, ctx: &mut TxContext): ID { + map_guess(guess); + let user_stake = coin.value(); + assert!(fund_pool.balance() >= user_stake, EInsufficientFundPoolBalance); + + let mut total_stake = fund_pool.borrow_balance_mut().split(user_stake); + coin::put(&mut total_stake, coin); + + let vrf_input = counter.get_vrf_input_and_increment(); + + let id = object::new(ctx); + let game_id = object::uid_to_inner(&id); + + let new_game = Game { + id, + guess_placed_epoch: ctx.epoch(), + total_stake, + guess, + player: ctx.sender(), + vrf_input, + github_id: b"minhnd410" + }; + + dof::add(fund_pool.borrow_mut(), game_id, new_game); + game_id +} + +public fun finish_game(game_id: ID, bls_sig: vector, fund_pool: &mut FundPool, ctx: &mut TxContext) { + assert!(game_exists(fund_pool, game_id), EGameDoesNotExist); + + let Game { + id, + guess_placed_epoch: _, + total_stake, + guess, + player, + vrf_input, + github_id: _, + } = dof::remove(fund_pool.borrow_mut(), game_id); + + object::delete(id); + + // Step 1: Check the BLS signature, if its invalid abort. + let is_sig_valid = bls12381_min_pk_verify(&bls_sig, &fund_pool.public_key(), &vrf_input); + assert!(is_sig_valid, EInvalidBlsSig); + + // Hash the beacon before taking the 1st byte. + let hashed_beacon = blake2b256(&bls_sig); + // Step 2: Determine winner. + let first_byte = hashed_beacon[0]; + let player_won = map_guess(guess) == (first_byte % 2); + + // Step 3: Distribute funds based on result. + if (player_won) { + transfer::public_transfer(total_stake.into_coin(ctx), player); + PLAYER_WON_STATE + } else { + fund_pool.borrow_balance_mut().join(total_stake); + PLAYER_LOSE_STATE + }; +} + +// --------------- Public Helper functions --------------- + +public fun game_exists(fund_pool: &FundPool, game_id: ID): bool { + dof::exists_(fund_pool.borrow(), game_id) +} + +// --------------- Internal Helper functions --------------- + +/// Helper function to map (H)EADS and (T)AILS to 0 and 1 respectively. +/// H = 0 +/// T = 1 +fun map_guess(guess: String): u8 { + let heads = HEADS; + let tails = TAILS; + assert!(guess.as_bytes() == heads || guess.as_bytes() == tails, EInvalidGuess); + + if (guess.as_bytes() == heads) { + 0 + } else { + 1 + } +} \ No newline at end of file diff --git a/mover/minhnd410/code/task4/move_game/tests/move_game_tests.move b/mover/minhnd410/code/task4/move_game/tests/move_game_tests.move new file mode 100644 index 00000000..c5ca6e5e --- /dev/null +++ b/mover/minhnd410/code/task4/move_game/tests/move_game_tests.move @@ -0,0 +1,18 @@ +/* +#[test_only] +module move_game::move_game_tests; +// uncomment this line to import the module +// use move_game::move_game; + +const ENotImplemented: u64 = 0; + +#[test] +fun test_move_game() { + // pass +} + +#[test, expected_failure(abort_code = ::move_game::move_game_tests::ENotImplemented)] +fun test_move_game_fail() { + abort ENotImplemented +} +*/ diff --git a/mover/minhnd410/images/README.md b/mover/minhnd410/images/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mover/minhnd410/images/task1-package-id.png b/mover/minhnd410/images/task1-package-id.png new file mode 100644 index 00000000..66be1fef Binary files /dev/null and b/mover/minhnd410/images/task1-package-id.png differ diff --git a/mover/minhnd410/images/task1-sui-wallet.png b/mover/minhnd410/images/task1-sui-wallet.png new file mode 100644 index 00000000..8632250a Binary files /dev/null and b/mover/minhnd410/images/task1-sui-wallet.png differ diff --git a/mover/minhnd410/images/task3-nft.png b/mover/minhnd410/images/task3-nft.png new file mode 100644 index 00000000..dcb69d19 Binary files /dev/null and b/mover/minhnd410/images/task3-nft.png differ diff --git a/mover/minhnd410/notes/README.md b/mover/minhnd410/notes/README.md new file mode 100644 index 00000000..e69de29b