From 966923e9008482ad43735279c235bd75c1f4df3f Mon Sep 17 00:00:00 2001 From: hardworking-toptal-dev <161673729+hardworking-toptal-dev@users.noreply.github.com> Date: Sun, 11 Aug 2024 02:02:18 +0900 Subject: [PATCH 01/14] feat: build own contract --- soroban-react-dapp/contracts/deployments.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soroban-react-dapp/contracts/deployments.json b/soroban-react-dapp/contracts/deployments.json index da99780..abd02d9 100644 --- a/soroban-react-dapp/contracts/deployments.json +++ b/soroban-react-dapp/contracts/deployments.json @@ -7,6 +7,6 @@ { "contractId": "greeting", "networkPassphrase": "Test SDF Network ; September 2015", - "contractAddress": "CDWGVPSUXXSGABQ663FVV4TZJH4Q2R3HVAKTKWFFFMWPF23O7KMNS4KU" + "contractAddress": "CDLD5YFQ3PSNUWQTY2UCD3UB7XKJE27ZEXPHR6XKU3UOQLRH66J6RLF3" } ] \ No newline at end of file From 658bdb6922e71b0ef783db4da9e0842a261c06eb Mon Sep 17 00:00:00 2001 From: hardworking-toptal-dev <161673729+hardworking-toptal-dev@users.noreply.github.com> Date: Sun, 11 Aug 2024 02:33:31 +0900 Subject: [PATCH 02/14] refactor: update smart contract with challenge's requirement --- .../contracts/greeting/src/lib.rs | 79 +++++++++++++++++-- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/soroban-react-dapp/contracts/greeting/src/lib.rs b/soroban-react-dapp/contracts/greeting/src/lib.rs index b6c9990..e2815b0 100755 --- a/soroban-react-dapp/contracts/greeting/src/lib.rs +++ b/soroban-react-dapp/contracts/greeting/src/lib.rs @@ -1,24 +1,89 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, Env, Symbol, symbol_short, String}; +use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, String, Symbol, Vec}; const TITLE: Symbol = symbol_short!("TITLE"); - #[contract] pub struct TitleContract; +#[contracterror] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + Unauthorized = 1, + AlreadyInitialized = 2, +} + #[contractimpl] impl TitleContract { + // initialize the contract and set the admin + pub fn init(env: Env, admin: Address) -> Result<(), Error> { + let storage = env.storage().instance(); + admin.require_auth(); + if storage.has(&Assets::Admin) { + return Err(Error::AlreadyInitialized); + } + storage.set(&Assets::Admin, &admin); + Ok(()) + } - pub fn set_title(env: Env, title: String) { - env.storage().instance().set(&TITLE, &title) + // set the title only available editors + pub fn set_title(env: Env, user: Address, title: String) { + user.require_auth(); + let storage = env.storage().instance(); + let admin: Address = storage.get(&Assets::Admin).unwrap(); + let editors: Vec
= storage.get(&Assets::Editors).unwrap_or(Vec::new(&env)); + if editors.contains(&user) || caller.eq(&admin) { + env.storage().instance().set(&Assets::Title, &title); + Ok(()) + } else { + Err(Error::Unauthorized) + } } + // read the title pub fn read_title(env: Env) -> String { - env.storage().instance().get(&TITLE) + env.storage() + .instance() + .get(&Assets::Title) .unwrap_or(String::from_str(&env, "Default Title")) } - -} + + /// ***** Address Management ***** /// + + // add wallet address for editors + pub fn add_editor(env: Env, new_editor: Address) { + let storage = env.storage().instance(); + let admin: Address = storage.get(&Assets::Admin).unwrap(); + admin.require_auth(); + + let mut editors: Vec = storage.get(&Assets::Editors).unwrap_or(Vec::new(&env)); + if !editors.contains(&new_editor) { + editors.push_front(new_editor); + env.storage().instance().set(&Assets::Editors, &editors); + } + } + + // remove wallets from editors + pub fn remove_admin(env: Env, remover: Address) { + let storage = env.storage().instance(); + let admin: Address = storage.get(&Assets::Admin).unwrap(); + admin.require_auth(); + + let mut admins: Vec = storage.get(&Assets::Editors).unwrap_or(Vec::new(&env)); + admins + .first_index_of(&remover) + .map(|index| admins.remove(index)); + env.storage().instance().set(&Assets::Editors, &admins); + } +} + +#[derive(Clone)] +#[contracttype] +pub enum Assets { + Admin, + Editors, + Title, +} mod test; From ca3391f60e58c39f0e200fead2d64f48ae17cfdc Mon Sep 17 00:00:00 2001 From: hardworking-toptal-dev <161673729+hardworking-toptal-dev@users.noreply.github.com> Date: Sun, 11 Aug 2024 02:40:21 +0900 Subject: [PATCH 03/14] chore: add some types --- soroban-react-dapp/contracts/greeting/src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/soroban-react-dapp/contracts/greeting/src/lib.rs b/soroban-react-dapp/contracts/greeting/src/lib.rs index e2815b0..afe9e03 100755 --- a/soroban-react-dapp/contracts/greeting/src/lib.rs +++ b/soroban-react-dapp/contracts/greeting/src/lib.rs @@ -1,5 +1,8 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, symbol_short, Address, Env, String, Symbol, Vec}; +use soroban_sdk::{ + contract, contracterror, contractimpl, contracttype, symbol_short, Address, Env, String, + Symbol, Vec, +}; const TITLE: Symbol = symbol_short!("TITLE"); @@ -28,12 +31,12 @@ impl TitleContract { } // set the title only available editors - pub fn set_title(env: Env, user: Address, title: String) { + pub fn set_title(env: Env, user: Address, title: String) -> Result<(), Error> { user.require_auth(); let storage = env.storage().instance(); let admin: Address = storage.get(&Assets::Admin).unwrap(); let editors: Vec = storage.get(&Assets::Editors).unwrap_or(Vec::new(&env)); - if editors.contains(&user) || caller.eq(&admin) { + if editors.contains(&user) || user.eq(&admin) { env.storage().instance().set(&Assets::Title, &title); Ok(()) } else { From 364966831c30717f5a1b02f28fd69ddf6627a4e9 Mon Sep 17 00:00:00 2001 From: hardworking-toptal-dev <161673729+hardworking-toptal-dev@users.noreply.github.com> Date: Sun, 11 Aug 2024 02:42:16 +0900 Subject: [PATCH 04/14] feat: finish and deploy smart contract --- soroban-react-dapp/contracts/deployments.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soroban-react-dapp/contracts/deployments.json b/soroban-react-dapp/contracts/deployments.json index abd02d9..455d673 100644 --- a/soroban-react-dapp/contracts/deployments.json +++ b/soroban-react-dapp/contracts/deployments.json @@ -7,6 +7,6 @@ { "contractId": "greeting", "networkPassphrase": "Test SDF Network ; September 2015", - "contractAddress": "CDLD5YFQ3PSNUWQTY2UCD3UB7XKJE27ZEXPHR6XKU3UOQLRH66J6RLF3" + "contractAddress": "CC7S2ADZBM7WUHD6JN6UPDQ7DY4QOCER7QQHXMGKUTJWXVTPXJUG7C3E" } ] \ No newline at end of file From 7cca58fac35bfdceb3d9d0248443051b2dcaf551 Mon Sep 17 00:00:00 2001 From: hardworking-toptal-dev <161673729+hardworking-toptal-dev@users.noreply.github.com> Date: Sun, 11 Aug 2024 10:19:38 +0900 Subject: [PATCH 05/14] feat: add test script --- soroban-react-dapp/contracts/deployments.json | 2 +- .../contracts/greeting/src/lib.rs | 2 +- .../contracts/greeting/src/test.rs | 37 +- .../greeting/test_snapshots/test/test.1.json | 788 ++++++++++++++++++ 4 files changed, 820 insertions(+), 9 deletions(-) create mode 100644 soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json diff --git a/soroban-react-dapp/contracts/deployments.json b/soroban-react-dapp/contracts/deployments.json index 455d673..d6c40b2 100644 --- a/soroban-react-dapp/contracts/deployments.json +++ b/soroban-react-dapp/contracts/deployments.json @@ -7,6 +7,6 @@ { "contractId": "greeting", "networkPassphrase": "Test SDF Network ; September 2015", - "contractAddress": "CC7S2ADZBM7WUHD6JN6UPDQ7DY4QOCER7QQHXMGKUTJWXVTPXJUG7C3E" + "contractAddress": "CAMHGS47DPLS7NXH5MP4AS74NOUBMCMUKG27K3PZJPKHWJNWUWIETDZV" } ] \ No newline at end of file diff --git a/soroban-react-dapp/contracts/greeting/src/lib.rs b/soroban-react-dapp/contracts/greeting/src/lib.rs index afe9e03..ff9a49b 100755 --- a/soroban-react-dapp/contracts/greeting/src/lib.rs +++ b/soroban-react-dapp/contracts/greeting/src/lib.rs @@ -68,7 +68,7 @@ impl TitleContract { } // remove wallets from editors - pub fn remove_admin(env: Env, remover: Address) { + pub fn remove_editor(env: Env, remover: Address) { let storage = env.storage().instance(); let admin: Address = storage.get(&Assets::Admin).unwrap(); admin.require_auth(); diff --git a/soroban-react-dapp/contracts/greeting/src/test.rs b/soroban-react-dapp/contracts/greeting/src/test.rs index b95c919..bfcde2c 100755 --- a/soroban-react-dapp/contracts/greeting/src/test.rs +++ b/soroban-react-dapp/contracts/greeting/src/test.rs @@ -1,21 +1,44 @@ #![cfg(test)] use super::*; -use soroban_sdk::{Env, String}; - +use soroban_sdk::{testutils::Address as _, Address, Env, String}; #[test] fn test() { + // test to mock the all auths let env = Env::default(); + env.mock_all_auths(); + let contract_id = env.register_contract(None, TitleContract); let client = TitleContractClient::new(&env, &contract_id); - let client_default_title = client.read_title(); - assert_eq!(client_default_title, String::from_slice(&env, "Default Title")); + let admin = Address::generate(&env); + let new_editor = Address::generate(&env); + + // init by admin + client.init(&admin); + + let client_default_title = client.read_title(); + assert_eq!( + client_default_title, + String::from_str(&env, "Default Title") + ); + + // test either everyone access to modify title or not + let _ = client.try_set_title(&new_editor, &String::from_str(&env, "Hello, Stellar")); + let client_title = client.read_title(); + assert_eq!(client_title, String::from_str(&env, "Default Title")); - client.set_title(&String::from_slice(&env, "My New Title")); - let client_new_title = client.read_title(); + // give edit access + client.add_editor(&new_editor); - assert_eq!(client_new_title, String::from_slice(&env, "My New Title")); + // mofify the title with editors + client.set_title(&new_editor, &String::from_str(&env, "Hello, Stellar")); + let client_new_title = client.read_title(); + assert_eq!(client_new_title, String::from_str(&env, "Hello, Stellar")); + // remove editors by admin + let _ = client.remove_editor(&new_editor); + // let admins = client.read_admins(); + // assert_eq!(admins.len(), 1); } diff --git a/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json b/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json new file mode 100644 index 0000000..c7184d9 --- /dev/null +++ b/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json @@ -0,0 +1,788 @@ +{ + "generators": { + "address": 3, + "nonce": 0 + }, + "auth": [ + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "init", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "add_editor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "set_title", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Hello, Stellar" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "remove_editor", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ] + ], + "ledger": { + "protocol_version": 21, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "vec": [ + { + "symbol": "Editors" + } + ] + }, + "val": { + "vec": [] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Title" + } + ] + }, + "val": { + "string": "Hello, Stellar" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2032731177588607455 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2032731177588607455 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 4837995959683129791 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_code": { + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [ + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "init" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "init" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "read_title" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "read_title" + } + ], + "data": { + "string": "Default Title" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "set_title" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Hello, Stellar" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "set_title" + } + ], + "data": { + "error": { + "contract": 1 + } + } + } + } + }, + "failed_call": true + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "error" + }, + { + "error": { + "contract": 1 + } + } + ], + "data": { + "string": "escalating Ok(ScErrorType::Contract) frame-exit to Err" + } + } + } + }, + "failed_call": true + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "error" + }, + { + "error": { + "contract": 1 + } + } + ], + "data": { + "vec": [ + { + "string": "contract try_call failed" + }, + { + "symbol": "set_title" + }, + { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Hello, Stellar" + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "read_title" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "read_title" + } + ], + "data": { + "string": "Default Title" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "add_editor" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "add_editor" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "set_title" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "Hello, Stellar" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "set_title" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "read_title" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "read_title" + } + ], + "data": { + "string": "Hello, Stellar" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "remove_editor" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "remove_editor" + } + ], + "data": "void" + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file From cf74475b149c6003787f88f84fb389180dc7b22a Mon Sep 17 00:00:00 2001 From: hardworking-toptal-dev <161673729+hardworking-toptal-dev@users.noreply.github.com> Date: Sun, 11 Aug 2024 10:26:58 +0900 Subject: [PATCH 06/14] chore: remove unnecessary values --- soroban-react-dapp/contracts/greeting/src/lib.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/soroban-react-dapp/contracts/greeting/src/lib.rs b/soroban-react-dapp/contracts/greeting/src/lib.rs index ff9a49b..428c483 100755 --- a/soroban-react-dapp/contracts/greeting/src/lib.rs +++ b/soroban-react-dapp/contracts/greeting/src/lib.rs @@ -1,10 +1,5 @@ #![no_std] -use soroban_sdk::{ - contract, contracterror, contractimpl, contracttype, symbol_short, Address, Env, String, - Symbol, Vec, -}; - -const TITLE: Symbol = symbol_short!("TITLE"); +use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, Env, String, Vec}; #[contract] pub struct TitleContract; From 7722c6def504f7549aed17d4ab210ac48768df2e Mon Sep 17 00:00:00 2001 From: hardworking-toptal-dev <161673729+hardworking-toptal-dev@users.noreply.github.com> Date: Sun, 11 Aug 2024 12:01:09 +0900 Subject: [PATCH 07/14] feat: add admin section in GreeterContractInteraction --- soroban-react-dapp/contracts/deployments.json | 2 +- .../contracts/greeting/src/lib.rs | 7 + .../contracts/greeting/src/test.rs | 4 +- .../greeting/test_snapshots/test/test.1.json | 50 +++- .../web3/GreeterContractInteractions.tsx | 243 +++++++++++++++--- 5 files changed, 268 insertions(+), 38 deletions(-) diff --git a/soroban-react-dapp/contracts/deployments.json b/soroban-react-dapp/contracts/deployments.json index d6c40b2..0abc5fd 100644 --- a/soroban-react-dapp/contracts/deployments.json +++ b/soroban-react-dapp/contracts/deployments.json @@ -7,6 +7,6 @@ { "contractId": "greeting", "networkPassphrase": "Test SDF Network ; September 2015", - "contractAddress": "CAMHGS47DPLS7NXH5MP4AS74NOUBMCMUKG27K3PZJPKHWJNWUWIETDZV" + "contractAddress": "CAAIO5RZEHFLUKN2F7LSGQOPSAJ6IJNJSVNLHTLX3M2VOGJV6ZBAI6GJ" } ] \ No newline at end of file diff --git a/soroban-react-dapp/contracts/greeting/src/lib.rs b/soroban-react-dapp/contracts/greeting/src/lib.rs index 428c483..7d01cd7 100755 --- a/soroban-react-dapp/contracts/greeting/src/lib.rs +++ b/soroban-react-dapp/contracts/greeting/src/lib.rs @@ -74,6 +74,13 @@ impl TitleContract { .map(|index| admins.remove(index)); env.storage().instance().set(&Assets::Editors, &admins); } + + // fetch the editor lists + pub fn fetch_editors(env: Env) -> Vec { + let storage = env.storage().instance(); + let editors: Vec = storage.get(&Assets::Editors).unwrap_or(Vec::new(&env)); + editors + } } #[derive(Clone)] diff --git a/soroban-react-dapp/contracts/greeting/src/test.rs b/soroban-react-dapp/contracts/greeting/src/test.rs index bfcde2c..6fab238 100755 --- a/soroban-react-dapp/contracts/greeting/src/test.rs +++ b/soroban-react-dapp/contracts/greeting/src/test.rs @@ -39,6 +39,6 @@ fn test() { // remove editors by admin let _ = client.remove_editor(&new_editor); - // let admins = client.read_admins(); - // assert_eq!(admins.len(), 1); + let admins = client.fetch_editors(); + assert_eq!(admins.len(), 0); } diff --git a/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json b/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json index c7184d9..7b4f00d 100644 --- a/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json +++ b/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json @@ -86,7 +86,8 @@ "sub_invocations": [] } ] - ] + ], + [] ], "ledger": { "protocol_version": 21, @@ -783,6 +784,53 @@ } }, "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "fetch_editors" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "fetch_editors" + } + ], + "data": { + "vec": [] + } + } + } + }, + "failed_call": false } ] } \ No newline at end of file diff --git a/soroban-react-dapp/src/components/web3/GreeterContractInteractions.tsx b/soroban-react-dapp/src/components/web3/GreeterContractInteractions.tsx index e22e0a8..8a0dea5 100644 --- a/soroban-react-dapp/src/components/web3/GreeterContractInteractions.tsx +++ b/soroban-react-dapp/src/components/web3/GreeterContractInteractions.tsx @@ -11,9 +11,12 @@ import React from 'react' import Link from 'next/link' import { contractInvoke, useRegisteredContract } from '@soroban-react/contracts' -import { nativeToScVal, xdr } from '@stellar/stellar-sdk' +import { Address, nativeToScVal, xdr } from '@stellar/stellar-sdk' +import { Adamina } from 'next/font/google' type UpdateGreetingValues = { newMessage: string } +type AddEditorValues = { newEditor: string } +type RemoveEditorValues = { remover: string } export const GreeterContractInteractions: FC = () => { const sorobanContext = useSorobanReact() @@ -21,22 +24,27 @@ export const GreeterContractInteractions: FC = () => { const [, setFetchIsLoading] = useState- {editor}
+ {i !== 0 && } +- {d.networkPassphrase}
- )) + )) }- + {contractAddressStored ? {contractAddressStored} : "Loading address.."}
- {editor}
+- {trimAddress(editor)}
{i !== 0 && } @@ -286,15 +291,15 @@ export const GreeterContractInteractions: FC = () => {