diff --git a/mover/longphu25/README.md b/mover/longphu25/README.md new file mode 100644 index 00000000..22c1ddf1 --- /dev/null +++ b/mover/longphu25/README.md @@ -0,0 +1,46 @@ +## Basic Information +- Sui Wallet Address: `0xde03f5aa56efbf3765da3b92425e1403f0820f574933073c13c47070fd56128b` +> First-time participants must complete the registration of the wallet address through the first task to have it merged. You should use this address for subsequent tasks. We will also use this address to credit the learning rewards. +- Github: `longphu25` + +## Personal Introduction +- Work Experience: `13 years` +- Tech Stack: `PHP` `Golang` `Rust` `C#` `Python` `Javascript` `Typescript` +> Important: Please take your personal introduction seriously. +- Years of experience in web2 development, particularly interested in Move, aiming to use Move as an entry point into blockchain. (This is just an example, please write your own introduction and feel free to add more details.) +- Contact: telegram `longphu` + +## Tasks + +### 01 hello move +- [x] Sui CLI Version: `sui 1.40.0-75a20fa8c1fa` +- [x] Sui Wallet Screenshot: ![](./images/sui-wallet.png) +- [x] Package ID: 0x145a559fe7127f1d908a91a2eca93efdb865849ca6e86afefbf62a6c453fa76c +- [x] Package ID's Screenshot from Explorer: ![](./images/sui-package.png) + +### 02 move coin +- [x] `My Coin` Package ID: 0xcb3af9597bca8d4cfd1f9995cce3fec8ffed9ed3d589526096ce441de5b6efb7 +- [x] `Faucet Coin` Package ID: 0x224f8dc5ce2b50aa05b1a2f7f3bc837c6488303482ac521ac0bbbe821277870b +- [x] Transfer `My Coin` hash: 3Jt2fLrktHcU7PjdirW2irXUU3QnoUAf81dio5E2AR1Q +- [x] `Faucet Coin` address 1 mint hash: BVNJ1ccTFc6M2Z1sUyWw6a2EeogNt3ZWY97J4Sr8UEtu +- [x] `Faucet Coin` address 2 mint hash: 9ETYyrpcJPuc9ceM493eQ5iHmypVYqk2mmwY597gVmPZ + +### 03 move nft +- [x] NFT Package ID: 0x064f81806b60a0ba739fcaaef8055ba46bdbffda8b83e1be1679196d331f761a +- [x] NFT Object ID: 0xacce2199f0944c053348f2ad7bb25effbf07bd8ae57786cfd01b078d20d69e0d +- [x] Transfer NFT hash: 2G6dRiBJGcr3ktCNCSY86Dm4rQdU24TwY5criAhtwgaE +- [x] NFT's Screenshot from Explorer: ![](./images/my-nft.png) + +### 04 move game +- [ ] Game Package ID: +- [ ] Deposit Coin Hash: +- [ ] Withdraw Coin Hash: +- [ ] Play Game Hash: + +### 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/longphu25/code/README.md b/mover/longphu25/code/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mover/longphu25/code/task1/Hello_Move/.gitignore b/mover/longphu25/code/task1/Hello_Move/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/longphu25/code/task1/Hello_Move/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/longphu25/code/task1/Hello_Move/Makefile b/mover/longphu25/code/task1/Hello_Move/Makefile new file mode 100644 index 00000000..6981ae55 --- /dev/null +++ b/mover/longphu25/code/task1/Hello_Move/Makefile @@ -0,0 +1,60 @@ +# https://docs.sui.io/references/cli/client +network: + sui client envs +version: + sui --version +address: # https://docs.sui.io/references/cli/cheatsheet + sui client address +new-address: + sui client new-address ed25519 +balance: + sui client balance +move-build: + sui move build +test: + sui move test +client-objects: + sui client objects +faucet: + sui client faucet +# https://docs.sui.io/guides/developer/first-app/publish +publish: + sui client publish + +# https://docs.sui.io/references/cli/cheatsheet#executing-transactions +# │ Published Objects: │ +# │ ┌── │ +# │ │ PackageID: 0x145a559fe7127f1d908a91a2eca93efdb865849ca6e86afefbf62a6c453fa76c │ +# │ │ Version: 1 │ +# │ │ Digest: GuKLuED88MVxgyhGfsa46cqo2LZPvaozJ5FhYTzU69Rj │ +# │ │ Modules: longphu │ +# │ └── │ +# ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ +call-package: + sui client call --package 0x145a559fe7127f1d908a91a2eca93efdb865849ca6e86afefbf62a6c453fa76c --module longphu --function say_hello + +view-object: + sui client object 0x61a19ec0244dacd834e0dbeab725b4d014962c879b2db69393050be549002591 + +keytool: + sui keytool list + +export-private-key: + sui keytool export --key-identity naughty-idocrase + +mint-my-coin: + sui client call --package 0xcb3af9597bca8d4cfd1f9995cce3fec8ffed9ed3d589526096ce441de5b6efb7 --module my_coin --function mint --args 0x01e060aca9d96cb9a710ae5c76be193b5b7d79968d7bebb7cb9a8c6838b5fbed 1000000000 0x052f5a900488ef4a6c130e395ea6c10d1b0d73e12adb7da43dfd5ef47ecd5a6e + +# ObjectType: 0x2::coin::TreasuryCap<0xcb3af9597bca8d4cfd1f9995cce3fec8ffed9ed3d589526096ce441de5b6efb7::my_coin::MY_COIN> + +mint-faucet-coin: + sui client call --package 0x224f8dc5ce2b50aa05b1a2f7f3bc837c6488303482ac521ac0bbbe821277870b --module faucet_coin --function mint --args 0xe986705f1fc23a91ec33f829899b930d376179a424c5771488d9337553d434b9 1000000000 0x052f5a900488ef4a6c130e395ea6c10d1b0d73e12adb7da43dfd5ef47ecd5a6e + +# ObjectID:0xe986705f1fc23a91ec33f829899b930d376179a424c5771488d9337553d434b9 +# ObjectType: 0x224f8dc5ce2b50aa05b1a2f7f3bc837c6488303482ac521ac0bbbe821277870b::faucet_coin::TreasuryCapKeeper + +call-package-nft: + sui client call --package 0x064f81806b60a0ba739fcaaef8055ba46bdbffda8b83e1be1679196d331f761a --module move_nft --function mint --args '' '' 0x052f5a900488ef4a6c130e395ea6c10d1b0d73e12adb7da43dfd5ef47ecd5a6e + +transfer-nft: + sui client transfer --to 0xa9ddd77d41119bdcbab0f5c4d18bf15e65034607afc5a296865f640e0d33d958 --object-id 0x9a12a04ef2c2f417bd62cf9702683afd2611e7d4ace1a23f3ade85c2cef9c27d \ No newline at end of file diff --git a/mover/longphu25/code/task1/Hello_Move/Move.lock b/mover/longphu25/code/task1/Hello_Move/Move.lock new file mode 100644 index 00000000..f61503f4 --- /dev/null +++ b/mover/longphu25/code/task1/Hello_Move/Move.lock @@ -0,0 +1,34 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "52664DA431D121453DE4A63E2A2EEFD5594CFC5E814D55AE51888BE5A9230629" +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.40.0" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0x145a559fe7127f1d908a91a2eca93efdb865849ca6e86afefbf62a6c453fa76c" +latest-published-id = "0x145a559fe7127f1d908a91a2eca93efdb865849ca6e86afefbf62a6c453fa76c" +published-version = "1" diff --git a/mover/longphu25/code/task1/Hello_Move/Move.toml b/mover/longphu25/code/task1/Hello_Move/Move.toml new file mode 100644 index 00000000..4412776d --- /dev/null +++ b/mover/longphu25/code/task1/Hello_Move/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/longphu25/code/task1/Hello_Move/sources/hello_move.move b/mover/longphu25/code/task1/Hello_Move/sources/hello_move.move new file mode 100644 index 00000000..efa54ddf --- /dev/null +++ b/mover/longphu25/code/task1/Hello_Move/sources/hello_move.move @@ -0,0 +1,31 @@ +/* +/// Module: hello_move +module hello_move::hello_move; +*/ + +// For Move coding conventions, see +// https://docs.sui.io/concepts/sui-move-concepts/conventions + + +module hello_move::longphu { + use std::string::{Self, String}; + + // Struct to store the GitHub ID + public struct GitHubStruct has key, store { + id: UID, + github_id: String, + } + + public entry fun say_hello(ctx: &mut TxContext) { + let hello_world = GitHubStruct { + id: object::new(ctx), + github_id: string::utf8(b"Long Phu"), + }; + + transfer::transfer(hello_world, tx_context::sender(ctx)); + } + + public fun github_id(github_object: &GitHubStruct): String { + github_object.github_id + } +} \ No newline at end of file diff --git a/mover/longphu25/code/task1/Hello_Move/tests/hello_move_tests.move b/mover/longphu25/code/task1/Hello_Move/tests/hello_move_tests.move new file mode 100644 index 00000000..aec835fc --- /dev/null +++ b/mover/longphu25/code/task1/Hello_Move/tests/hello_move_tests.move @@ -0,0 +1,48 @@ +/* +#[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 +} +*/ +#[test_only] +module hello_move::longphu_tests; +// uncomment this line to import the module +use hello_move::longphu::{GitHubStruct, say_hello, github_id}; +use sui::test_scenario; +use std::string; +use sui::test_utils::assert_eq; + +#[test] +fun test_call_say_hello_longphu() { + + let sender = @0x1e0; + + let mut scenario = test_scenario::begin(sender); + { + say_hello(test_scenario::ctx(&mut scenario)) + }; + + test_scenario::next_tx(&mut scenario, sender); + { + let received_object = test_scenario::take_from_sender(&scenario); + assert_eq(github_id(&received_object), string::utf8(b"Long Phu")); + + scenario.return_to_sender(received_object); + }; + + + test_scenario::end(scenario); +} + diff --git a/mover/longphu25/code/task1/README.md b/mover/longphu25/code/task1/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mover/longphu25/code/task2/faucet_coin/.gitignore b/mover/longphu25/code/task2/faucet_coin/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/longphu25/code/task2/faucet_coin/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/longphu25/code/task2/faucet_coin/Move.lock b/mover/longphu25/code/task2/faucet_coin/Move.lock new file mode 100644 index 00000000..b4019d5b --- /dev/null +++ b/mover/longphu25/code/task2/faucet_coin/Move.lock @@ -0,0 +1,34 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "F8CFCF256E2F1BB7CD401C27799A09C40777C5C100F0DFA253E86DD7F0D4ED1B" +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.40.0" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0x224f8dc5ce2b50aa05b1a2f7f3bc837c6488303482ac521ac0bbbe821277870b" +latest-published-id = "0x224f8dc5ce2b50aa05b1a2f7f3bc837c6488303482ac521ac0bbbe821277870b" +published-version = "1" diff --git a/mover/longphu25/code/task2/faucet_coin/Move.toml b/mover/longphu25/code/task2/faucet_coin/Move.toml new file mode 100644 index 00000000..1b517a2b --- /dev/null +++ b/mover/longphu25/code/task2/faucet_coin/Move.toml @@ -0,0 +1,37 @@ +[package] +name = "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] +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/longphu25/code/task2/faucet_coin/sources/faucet_coin.move b/mover/longphu25/code/task2/faucet_coin/sources/faucet_coin.move new file mode 100644 index 00000000..f4dfcf53 --- /dev/null +++ b/mover/longphu25/code/task2/faucet_coin/sources/faucet_coin.move @@ -0,0 +1,55 @@ +/* +/// Module: faucet_coin +module faucet_coin::faucet_coin; + +A Coin that anyone can mint. +*/ + +// For Move coding conventions, see +// https://docs.sui.io/concepts/sui-move-concepts/conventions + +module faucet_coin::faucet_coin { + use sui::coin::{Self, TreasuryCap}; + use sui::url; + + public struct FAUCET_COIN has drop {} + + public struct TreasuryCapKeeper has key, store { + id: UID, + cap: TreasuryCap + } + + fun init(otw: FAUCET_COIN, ctx: &mut TxContext) { + let (treasury_cap, metadata) = coin::create_currency( + otw, + 6, + b"LPFC", + b"LongPhu Faucet Coin", + b"The Faucet Coin is a coin that anyone can mint.", + option::some(url::new_unsafe_from_bytes(b"https://raw.githubusercontent.com/longphu25/lets-move/refs/heads/task2/mover/longphu25/images/faucet-coin.png")), + ctx + ); + + transfer::public_freeze_object(metadata); + transfer::public_share_object(TreasuryCapKeeper { + id: object::new(ctx), + cap: treasury_cap + }); + } + + public entry fun mint(keeper: &mut TreasuryCapKeeper, amount: u64, recipient: address, ctx: &mut TxContext) { + coin::mint_and_transfer(&mut keeper.cap, amount, recipient, ctx); + } + + public fun get_cap(keeper: &TreasuryCapKeeper): &TreasuryCap { + &keeper.cap + } + + #[test_only] + public fun init_for_testing(ctx: &mut TxContext) { + init(FAUCET_COIN{}, ctx); + } + +} + + diff --git a/mover/longphu25/code/task2/faucet_coin/tests/faucet_coin_tests.move b/mover/longphu25/code/task2/faucet_coin/tests/faucet_coin_tests.move new file mode 100644 index 00000000..8996846d --- /dev/null +++ b/mover/longphu25/code/task2/faucet_coin/tests/faucet_coin_tests.move @@ -0,0 +1,74 @@ +/* +#[test_only] +module faucet_coin::faucet_coin_tests; +// uncomment this line to import the module +// use faucet_coin::faucet_coin; + +const ENotImplemented: u64 = 0; + +#[test] +fun test_faucet_coin() { + // pass +} + +#[test, expected_failure(abort_code = ::faucet_coin::faucet_coin_tests::ENotImplemented)] +fun test_faucet_coin_fail() { + abort ENotImplemented +} +*/ + + +#[test_only] +module faucet_coin::faucet_coin_tests; +// uncomment this line to import the module +use faucet_coin::faucet_coin::{init_for_testing, mint, TreasuryCapKeeper, get_cap}; +use sui::test_scenario; +use sui::test_utils::{assert_eq}; +use sui::coin::{total_supply}; + +#[test] +fun test_faucet_coin() { + + let alice = @0x1e0; + let bob = @0x1e1; + let charlie = @0x1e2; + + let mut scenario = test_scenario::begin(alice); + { + init_for_testing(test_scenario::ctx(&mut scenario)) + }; + + test_scenario::next_tx(&mut scenario, bob); + { + let mut keeper = test_scenario::take_shared(&scenario); + mint(&mut keeper, 1001, charlie, test_scenario::ctx(&mut scenario)); + test_scenario::return_shared(keeper); + }; + + test_scenario::next_tx(&mut scenario, bob); + { + let keeper = test_scenario::take_shared(&scenario); + let cap = get_cap(&keeper); + let total_supply = total_supply(cap); + assert_eq(total_supply, 1001); + test_scenario::return_shared(keeper); + }; + + test_scenario::next_tx(&mut scenario, charlie); + { + let mut keeper = test_scenario::take_shared(&scenario); + mint(&mut keeper, 1001, alice, test_scenario::ctx(&mut scenario)); + test_scenario::return_shared(keeper); + }; + + test_scenario::next_tx(&mut scenario, charlie); + { + let keeper = test_scenario::take_shared(&scenario); + let cap = get_cap(&keeper); + let total_supply = total_supply(cap); + assert_eq(total_supply, 2002); + test_scenario::return_shared(keeper); + }; + + test_scenario::end(scenario); +} diff --git a/mover/longphu25/code/task2/my_coin/.gitignore b/mover/longphu25/code/task2/my_coin/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/longphu25/code/task2/my_coin/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/longphu25/code/task2/my_coin/Move.lock b/mover/longphu25/code/task2/my_coin/Move.lock new file mode 100644 index 00000000..2569ca0e --- /dev/null +++ b/mover/longphu25/code/task2/my_coin/Move.lock @@ -0,0 +1,34 @@ +# @generated by Move, please check-in and do not edit manually. + +[move] +version = 3 +manifest_digest = "0A4652D38CF3C3FDB79EC6C1C98FCFF7B2E933E12B84A1DA267DB28F66AFECE3" +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.40.0" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0xcb3af9597bca8d4cfd1f9995cce3fec8ffed9ed3d589526096ce441de5b6efb7" +latest-published-id = "0xcb3af9597bca8d4cfd1f9995cce3fec8ffed9ed3d589526096ce441de5b6efb7" +published-version = "1" diff --git a/mover/longphu25/code/task2/my_coin/Move.toml b/mover/longphu25/code/task2/my_coin/Move.toml new file mode 100644 index 00000000..b9ca003f --- /dev/null +++ b/mover/longphu25/code/task2/my_coin/Move.toml @@ -0,0 +1,37 @@ +[package] +name = "my_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] +my_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/longphu25/code/task2/my_coin/sources/my_coin.move b/mover/longphu25/code/task2/my_coin/sources/my_coin.move new file mode 100644 index 00000000..3caf19b6 --- /dev/null +++ b/mover/longphu25/code/task2/my_coin/sources/my_coin.move @@ -0,0 +1,39 @@ +/* +/// Module: my_coin +module my_coin::my_coin; +*/ + +// For Move coding conventions, see +// https://docs.sui.io/concepts/sui-move-concepts/conventions + +module my_coin::my_coin { + use sui::coin::{Self, TreasuryCap}; + use sui::url; + + public struct MY_COIN has drop {} + + fun init(otw: MY_COIN, ctx: &mut TxContext) { + let (treasury_cap, metadata) = coin::create_currency( + otw, + 6, + b"LP", + b"LongPhu Coin", + b"My Coin is a coin that only specific addresses can mint.", + option::some(url::new_unsafe_from_bytes(b"https://raw.githubusercontent.com/longphu25/lets-move/refs/heads/task2/mover/longphu25/images/my-coin.png")), + ctx + ); + + transfer::public_freeze_object(metadata); + transfer::public_transfer(treasury_cap, tx_context::sender(ctx)); + } + + public entry fun mint(tc: &mut TreasuryCap, amount: u64, recipient: address, ctx: &mut TxContext) { + coin::mint_and_transfer(tc, amount, recipient, ctx); + } + + + #[test_only] + public fun init_for_testing(ctx: &mut TxContext) { + init(MY_COIN{}, ctx); + } +} diff --git a/mover/longphu25/code/task2/my_coin/tests/my_coin_tests.move b/mover/longphu25/code/task2/my_coin/tests/my_coin_tests.move new file mode 100644 index 00000000..5300ae6b --- /dev/null +++ b/mover/longphu25/code/task2/my_coin/tests/my_coin_tests.move @@ -0,0 +1,104 @@ +/* +#[test_only] +module my_coin::my_coin_tests; +// uncomment this line to import the module +// use my_coin::my_coin; + +const ENotImplemented: u64 = 0; + +#[test] +fun test_my_coin() { + // pass +} + +#[test, expected_failure(abort_code = ::my_coin::my_coin_tests::ENotImplemented)] +fun test_my_coin_fail() { + abort ENotImplemented +} +*/ +#[test_only] +module my_coin::my_coin_tests; +// uncomment this line to import the module +use my_coin::my_coin::{MY_COIN, init_for_testing, mint}; +use sui::test_scenario; +use sui::test_utils::{assert_eq}; +use sui::coin::{TreasuryCap, total_supply}; +#[test] +fun test_my_coin() { + let alice = @0x1e0; + let bob = @0x1e1; + let charlie = @0x1e2; + + // Initialize the scenario with Alice as the sender + let mut scenario = test_scenario::begin(alice); + { + init_for_testing(test_scenario::ctx(&mut scenario)) + }; + + // Mint 10,000,000,000 MY_COIN to Bob by Alice + test_scenario::next_tx(&mut scenario, alice); + { + let mut tc = test_scenario::take_from_sender>(&scenario); + mint(&mut tc, 10000000000, bob, test_scenario::ctx(&mut scenario)); + scenario.return_to_sender(tc); + }; + + // Check the total supply of MY_COIN + test_scenario::next_tx(&mut scenario, alice); + { + let tc = test_scenario::take_from_sender>(&scenario); + let total_supply = total_supply(&tc); + assert_eq(total_supply, 10000000000); + scenario.return_to_sender(tc); + }; + + // Transfer minting permission to Bob + test_scenario::next_tx(&mut scenario, alice); + { + let tc = test_scenario::take_from_sender>(&scenario); + transfer::public_transfer(tc, bob); + }; + + // Mint 10,000,000,000 MY_COIN to Charlie by Bob + test_scenario::next_tx(&mut scenario, bob); + { + let mut tc = test_scenario::take_from_sender>(&scenario); + mint(&mut tc, 10000000000, charlie, test_scenario::ctx(&mut scenario)); + scenario.return_to_sender(tc); + }; + + // Check the total supply of MY_COIN + test_scenario::next_tx(&mut scenario, bob); + { + let tc = test_scenario::take_from_sender>(&scenario); + let total_supply = total_supply(&tc); + assert_eq(total_supply, 20000000000); + scenario.return_to_sender(tc); + }; + + test_scenario::end(scenario); +} + +#[test] +#[expected_failure] +fun test_my_coin_fail() { + let alice = @0x1e0; + let bob = @0x1e1; + let charlie = @0x1e2; + + // Initialize the scenario with Alice as the sender + let mut scenario = test_scenario::begin(alice); + { + init_for_testing(test_scenario::ctx(&mut scenario)) + }; + + // Mint 10,000,000,000 MY_COIN to Charlie by Bob (should fail) + test_scenario::next_tx(&mut scenario, bob); + { + let mut tc = test_scenario::take_from_sender>(&scenario); + mint(&mut tc, 10000000000, charlie, test_scenario::ctx(&mut scenario)); + scenario.return_to_sender(tc); + }; + + test_scenario::end(scenario); +} diff --git a/mover/longphu25/code/task3/move_nft/.gitignore b/mover/longphu25/code/task3/move_nft/.gitignore new file mode 100644 index 00000000..a007feab --- /dev/null +++ b/mover/longphu25/code/task3/move_nft/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/mover/longphu25/code/task3/move_nft/Move.lock b/mover/longphu25/code/task3/move_nft/Move.lock new file mode 100644 index 00000000..8e02f7f6 --- /dev/null +++ b/mover/longphu25/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.40.0" +edition = "2024.beta" +flavor = "sui" + +[env] + +[env.testnet] +chain-id = "4c78adac" +original-published-id = "0x064f81806b60a0ba739fcaaef8055ba46bdbffda8b83e1be1679196d331f761a" +latest-published-id = "0x064f81806b60a0ba739fcaaef8055ba46bdbffda8b83e1be1679196d331f761a" +published-version = "1" diff --git a/mover/longphu25/code/task3/move_nft/Move.toml b/mover/longphu25/code/task3/move_nft/Move.toml new file mode 100644 index 00000000..eb96b74d --- /dev/null +++ b/mover/longphu25/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/longphu25/code/task3/move_nft/sources/move_nft.move b/mover/longphu25/code/task3/move_nft/sources/move_nft.move new file mode 100644 index 00000000..a4b336ca --- /dev/null +++ b/mover/longphu25/code/task3/move_nft/sources/move_nft.move @@ -0,0 +1,67 @@ +/* +/// Module: move_nft +module move_nft::move_nft; +*/ + +// For Move coding conventions, see +// https://docs.sui.io/concepts/sui-move-concepts/conventions + +/* +- Complete the study of NFT-related concepts. +- Deploy a contract on the mainnet that allows minting of NFTs. +- Mint an NFT to your own address. +- The NFT image must be your GitHub avatar. +- Mint an NFT and send it to the address: `0xa9ddd77d41119bdcbab0f5c4d18bf15e65034607afc5a296865f640e0d33d958` +- Submit a screenshot of the blockchain explorer showing the NFT minted to your own address. +*/ + +module move_nft::move_nft { + use sui::url::{Self, Url}; + use std::string::{Self, String}; + + const GITHUB_ID: vector = b"longphu25"; + const URL: vector = b"https://avatars.githubusercontent.com/longphu25"; + + public struct StructNFT has key, store { + id: UID, + name: String, + description: String, + url: Url, + github_id: String, + } + + /// Get the NFT's `name` + public fun name(nft: &StructNFT): &string::String { + &nft.name + } + + /// Get the NFT's `description` + public fun description(nft: &StructNFT): &string::String { + &nft.description + } + + /// Get the NFT's `url` + public fun url(nft: &StructNFT): &Url { + &nft.url + } + + /// Get the NFT's `github_id` + public fun github_id(nft: &StructNFT): &string::String { + &nft.github_id + } + + public entry fun mint(name: vector, description: vector, recipient: address, ctx: &mut TxContext) { + let mut nft_name = GITHUB_ID.to_string(); + nft_name.append(b" ".to_string()); + nft_name.append(name.to_string()); + let nft = StructNFT { + id: object::new(ctx), + name: nft_name, + description: string::utf8(description), + url: url::new_unsafe_from_bytes(URL), + github_id: string::utf8(GITHUB_ID), + }; + + transfer::public_transfer(nft, recipient); + } +} diff --git a/mover/longphu25/code/task3/move_nft/tests/move_nft_tests.move b/mover/longphu25/code/task3/move_nft/tests/move_nft_tests.move new file mode 100644 index 00000000..e9e692b0 --- /dev/null +++ b/mover/longphu25/code/task3/move_nft/tests/move_nft_tests.move @@ -0,0 +1,59 @@ +/* +#[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 +} +*/ + +#[test_only] +module move_nft::move_nft_tests; +// uncomment this line to import the module +use move_nft::move_nft::{mint, StructNFT}; +use sui::test_scenario; +use sui::test_utils::{assert_eq}; +use std::string; +use sui::url; + +const GITHUB_ID: vector = b"longphu25"; +const URL: vector = b"https://avatars.githubusercontent.com/longphu25"; + + +#[test] +fun test_move_nft() { + let alice = @0x1e0; + let bob = @0x1e1; + + // Mint a nft to Bob by Alice + let mut scenario = test_scenario::begin(alice); + { + mint(b"NFT", b"This is a Move NFT", bob, test_scenario::ctx(&mut scenario)); + }; + + // Check Bob's nft + test_scenario::next_tx(&mut scenario, bob); + { + let nft = test_scenario::take_from_sender(&scenario); + let mut nft_name = GITHUB_ID.to_string(); + nft_name.append(b" ".to_string()); + nft_name.append(b"NFT".to_string()); + assert_eq(*nft.name(), nft_name); + assert_eq(*nft.description(), string::utf8(b"This is a Move NFT")); + assert_eq(*nft.url(), url::new_unsafe_from_bytes(URL)); + assert_eq(*nft.github_id(), string::utf8(GITHUB_ID)); + scenario.return_to_sender(nft); + }; + + test_scenario::end(scenario); +} diff --git a/mover/longphu25/images/README.md b/mover/longphu25/images/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mover/longphu25/images/faucet-coin.png b/mover/longphu25/images/faucet-coin.png new file mode 100644 index 00000000..a34af91e Binary files /dev/null and b/mover/longphu25/images/faucet-coin.png differ diff --git a/mover/longphu25/images/my-coin.png b/mover/longphu25/images/my-coin.png new file mode 100644 index 00000000..a1ba929b Binary files /dev/null and b/mover/longphu25/images/my-coin.png differ diff --git a/mover/longphu25/images/sui-package.png b/mover/longphu25/images/sui-package.png new file mode 100644 index 00000000..749f8781 Binary files /dev/null and b/mover/longphu25/images/sui-package.png differ diff --git a/mover/longphu25/images/sui-wallet.png b/mover/longphu25/images/sui-wallet.png new file mode 100644 index 00000000..3cb1bac6 Binary files /dev/null and b/mover/longphu25/images/sui-wallet.png differ diff --git a/mover/longphu25/notes/README.md b/mover/longphu25/notes/README.md new file mode 100644 index 00000000..e69de29b