From 1be2729c3dccbec16ec81ab84d027bfb448e8048 Mon Sep 17 00:00:00 2001 From: "daniel.andrade1991@gmail.com" Date: Wed, 21 Aug 2024 01:46:35 -0400 Subject: [PATCH 1/5] "My first dapp, check readme" --- .../.soroban/identity/admin.toml | 1 + soroban-react-dapp/README.md | 59 +- soroban-react-dapp/contracts/.env.example | 5 - soroban-react-dapp/contracts/deployments.json | 7 +- .../greeting/test_snapshots/test/test.1.json | 228 +++ soroban-react-dapp/contracts/package.json | 3 +- .../contracts/scripts/test_title.ts | 142 ++ soroban-react-dapp/contracts/title/Cargo.lock | 1451 +++++++++++++++++ soroban-react-dapp/contracts/title/Cargo.toml | 27 + soroban-react-dapp/contracts/title/Makefile | 15 + soroban-react-dapp/contracts/title/README.md | 15 + .../contracts/title/greeting.test.ts | 24 + soroban-react-dapp/contracts/title/src/lib.rs | 66 + .../contracts/title/src/test.rs | 116 ++ .../contracts/utils/contract.ts | 5 +- .../src/components/web3/ManageTitle.tsx | 138 ++ soroban-react-dapp/src/pages/index.tsx | 3 +- yarn.lock | 476 ++++++ 18 files changed, 2770 insertions(+), 11 deletions(-) create mode 100644 soroban-react-dapp/.soroban/identity/admin.toml delete mode 100644 soroban-react-dapp/contracts/.env.example create mode 100644 soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json create mode 100644 soroban-react-dapp/contracts/scripts/test_title.ts create mode 100644 soroban-react-dapp/contracts/title/Cargo.lock create mode 100755 soroban-react-dapp/contracts/title/Cargo.toml create mode 100755 soroban-react-dapp/contracts/title/Makefile create mode 100755 soroban-react-dapp/contracts/title/README.md create mode 100644 soroban-react-dapp/contracts/title/greeting.test.ts create mode 100755 soroban-react-dapp/contracts/title/src/lib.rs create mode 100755 soroban-react-dapp/contracts/title/src/test.rs create mode 100644 soroban-react-dapp/src/components/web3/ManageTitle.tsx create mode 100644 yarn.lock diff --git a/soroban-react-dapp/.soroban/identity/admin.toml b/soroban-react-dapp/.soroban/identity/admin.toml new file mode 100644 index 0000000..2872b71 --- /dev/null +++ b/soroban-react-dapp/.soroban/identity/admin.toml @@ -0,0 +1 @@ +secret_key = "SDDWPQWJFO7UGGFUBOZ4HZJDPBA62MWY3NUK7QTRL2LOTUVT5J3CRY7H" diff --git a/soroban-react-dapp/README.md b/soroban-react-dapp/README.md index 766edd8..b6bc803 100644 --- a/soroban-react-dapp/README.md +++ b/soroban-react-dapp/README.md @@ -1,3 +1,59 @@ +🛡️ Welcome to Title Contract + +Hello and welcome to Title Contract! 🎉 + +🚀 What is Title? + +Title is a special wallet containing the following crucial data: + + Account Admin: + Public Key: GA4HKU3GDGZHSUOAW6X3NQHG36EX4M5Z7THNWVXJA6GKTDHOI27OKUGI + Secret Key: SDDWPQWJFO7UGGFUBOZ4HZJDPBA62MWY3NUK7QTRL2LOTUVT5J3CRY7H + +This contract is the guardian that decides who can change the character associated with the wallet. Only those who know "the magic trick" will have that power. +🛠️ Project Setup +1. Environment Configuration readme soroban-react-dapp + +First, ensure that Soroban is set up in your environment. If you haven’t done so yet, you can add the admin identity by running: + +bash + +soroban config identity add --secret-key admin + +And, of course, you’ll need to input the secret key for Title (listed above). +2. Build and Testnet + +Next, build and deploy the contract on the testnet. Simply run: + +bash + +yarn deploy testnet title + +yarn testtitle testnet + +This should execute like so: + +bash + +root@3b15f88a2fa0:/workspace/contracts# yarn testtitle testnet + +3. Launch the Application + +Now that the contract is set up, it’s time to see the magic in action. Start the application with: + +bash + +yarn dev + +Watch what happens and get ready to explore! +4. Freight Configuration + +Don’t forget to configure Freight with Title to efficiently manage your tests. +5. Additional Testing + +Finally, add more test addresses to ensure that only those chosen by Title can change the character. Test the security of your contract and have fun in the process! + + # Welcome to your soroban react dapp boilerplate! This dapp largely inspired by the [ink!athon](https://github.com/scio-labs/inkathon) project will help you kickstart your soroban dapp creator journey. @@ -96,4 +152,5 @@ You then need to adapt the `contractInvoke()` calls in these functions to match Finally feel, of course, free to change the front-end how you wish, to match your desired functionalities. -*Good luck building!* \ No newline at end of file +*Good luck building!* + diff --git a/soroban-react-dapp/contracts/.env.example b/soroban-react-dapp/contracts/.env.example deleted file mode 100644 index cc141d7..0000000 --- a/soroban-react-dapp/contracts/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -# Stellar accounts Secret Keys -ADMIN_SECRET_KEY= - -# RPC Setup -MAINNET_RPC_URL= \ No newline at end of file diff --git a/soroban-react-dapp/contracts/deployments.json b/soroban-react-dapp/contracts/deployments.json index da99780..2e81167 100644 --- a/soroban-react-dapp/contracts/deployments.json +++ b/soroban-react-dapp/contracts/deployments.json @@ -7,6 +7,11 @@ { "contractId": "greeting", "networkPassphrase": "Test SDF Network ; September 2015", - "contractAddress": "CDWGVPSUXXSGABQ663FVV4TZJH4Q2R3HVAKTKWFFFMWPF23O7KMNS4KU" + "contractAddress": "CBYZPXMH3T7S6SAATE66NPA6JOIWE6NPYLVPFTOS73VGKPIHLW2MFDKE" + }, + { + "contractId": "title", + "networkPassphrase": "Test SDF Network ; September 2015", + "contractAddress": "CD2K6QRWVSTH5C2JPO455BNKS5WOOH5PVBP5SQS2TLDYZFQYZSNDJJAH" } ] \ No newline at end of file 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..d05611f --- /dev/null +++ b/soroban-react-dapp/contracts/greeting/test_snapshots/test/test.1.json @@ -0,0 +1,228 @@ +{ + "generators": { + "address": 1, + "nonce": 0 + }, + "auth": [ + [], + [], + [] + ], + "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": { + "symbol": "TITLE" + }, + "val": { + "string": "My New Title" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "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": "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": { + "string": "My New Title" + } + } + } + }, + "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": "My New Title" + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/soroban-react-dapp/contracts/package.json b/soroban-react-dapp/contracts/package.json index f9e6367..744175a 100644 --- a/soroban-react-dapp/contracts/package.json +++ b/soroban-react-dapp/contracts/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "build": "tsc", - "deploy": "yarn build && node dist/scripts/deploy.js" + "deploy": "yarn build && node dist/scripts/deploy.js", + "testtitle": "yarn build && node dist/scripts/test_title.js" }, "license": "MIT", "devDependencies": { diff --git a/soroban-react-dapp/contracts/scripts/test_title.ts b/soroban-react-dapp/contracts/scripts/test_title.ts new file mode 100644 index 0000000..2759867 --- /dev/null +++ b/soroban-react-dapp/contracts/scripts/test_title.ts @@ -0,0 +1,142 @@ +import { Address, nativeToScVal, scValToNative, xdr } from '@stellar/stellar-sdk'; +import { AddressBook } from '../utils/address_book.js'; +import { invokeContract, airdropAccount } from '../utils/contract.js'; +import { config } from '../utils/env_config.js'; + +export async function testTitleContract(addressBook: AddressBook) { + console.log('-------------------------------------------------------'); + console.log('Testing Title Contract'); + console.log('-------------------------------------------------------'); + + const admin = loadedConfig.admin; + const user_1 = loadedConfig.getUser("USER_1"); + const user_2 = loadedConfig.getUser("USER_2"); + + if (network !== "mainnet") { + await airdropAccount(admin); + await airdropAccount(user_1); + await airdropAccount(user_2); + } + + //Set admin + // console.log('-------------------------------------------------------'); + // console.log('Setting Admin'); + // console.log('-------------------------------------------------------'); + + // const params_set_admin: xdr.ScVal[] = [ + // new Address(admin.publicKey()).toScVal(), + // ]; + + // const result_set_admin = await invokeContract( + // 'title', + // addressBook, + // 'set_admin', + // params_set_admin, + // admin + // ); + // console.log("Result of set_admin: ", result_set_admin); + + // Add user + console.log('-------------------------------------------------------'); + console.log('Adding User'); + console.log('-------------------------------------------------------'); + + const params_add_user: xdr.ScVal[] = [ + new Address(user_1.publicKey()).toScVal(), + ]; + + const result_add_user = await invokeContract( + 'title', + addressBook, + 'add_user', + params_add_user, + admin // The admin adds the user + ); + console.log("Result of add_user: ", result_add_user); + + // Attempt to modify title with authorized user + console.log('-------------------------------------------------------'); + console.log('Modifying Title with Authorized User'); + console.log('-------------------------------------------------------'); + + const params_modify_title: xdr.ScVal[] = [ + new Address(user_1.publicKey()).toScVal(), + nativeToScVal("New Title", { type: "string" }) + ]; + + const result_modify_title = await invokeContract( + 'title', + addressBook, + 'modify_title', + params_modify_title, + user_1 + ); + console.log("Result of modify_title: ", result_modify_title); + + // Get title after modification + console.log('-------------------------------------------------------'); + console.log('Getting Title After Modification'); + console.log('-------------------------------------------------------'); + + const result_get_title = await invokeContract( + 'title', + addressBook, + 'get_title', + [], + admin, // Admin retrieves the title + true + ); + if (result_get_title && result_get_title.result && result_get_title.result.retval) { + console.log("Title after modification: ", scValToNative(result_get_title.result.retval)); + } else { + console.error("Error: Unable to retrieve title, result is undefined or invalid."); + } + + console.log("Title after modification: ", scValToNative(result_get_title.result.retval)); + + // Attempt to modify title with unauthorized user + console.log('-------------------------------------------------------'); + console.log('Modifying Title with Unauthorized User'); + console.log('-------------------------------------------------------'); + + const params_modify_title_unauthorized: xdr.ScVal[] = [ + new Address(user_2.publicKey()).toScVal(), + nativeToScVal("New Title", { type: "string" }) + ]; + + try { + const result_modify_title_unauthorized = await invokeContract( + 'title', + addressBook, + 'modify_title', + params_modify_title_unauthorized, + user_2 + ); + console.log("Unexpected success in unauthorized modify_title: ", result_modify_title_unauthorized); + } catch (e) { + const error = e as Error; + console.log("Expected failure in unauthorized modify_title: ", error.message); + } + + // Get admin address + console.log('-------------------------------------------------------'); + console.log('Getting Admin Address'); + console.log('-------------------------------------------------------'); + + const result_address_admin = await invokeContract( + 'title', + addressBook, + 'address_admin', + [], + admin, // Admin should be able to get the address + true + ); + console.log("Admin address: ", scValToNative(result_address_admin.result.retval)); +} + +const network = process.argv[2]; +const loadedConfig = config(network); + +const addressBook = AddressBook.loadFromFile(network, loadedConfig); + +await testTitleContract(addressBook); diff --git a/soroban-react-dapp/contracts/title/Cargo.lock b/soroban-react-dapp/contracts/title/Cargo.lock new file mode 100644 index 0000000..51429f8 --- /dev/null +++ b/soroban-react-dapp/contracts/title/Cargo.lock @@ -0,0 +1,1451 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base32" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" + +[[package]] +name = "bytes-lit" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adabf37211a5276e46335feabcbb1530c95eb3fdf85f324c7db942770aa025d" +dependencies = [ + "num-bigint", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "iana-time-zone", + "num-integer", + "num-traits", + "serde", + "winapi", +] + +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +dependencies = [ + "libc", +] + +[[package]] +name = "crate-git-revision" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c521bf1f43d31ed2f73441775ed31935d77901cb3451e44b38a1c1612fcbaf98" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f34ba9a9bcb8645379e9de8cb3ecfcf4d1c85ba66d90deb3259206fa5aa193b" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "ecdsa" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "escape-bytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bfcf67fea2815c2fc3b90873fae90957be12ff417335dfadc7f52927feb03b2" + +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "primeorder" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7dbe9ed3b56368bd99483eb32fe9c17fdd3730aebadc906918ce78d54c7eeb4" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "sec1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +dependencies = [ + "base16ct", + "der", + "generic-array", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + +[[package]] +name = "serde" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.192" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +dependencies = [ + "base64 0.21.2", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.1.0", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "soroban-builtin-sdk-macros" +version = "21.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa78f4b1c752f5471b033fe54279ef0617ace342be7be11acc7d90e5677790e" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "soroban-env-common" +version = "21.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9acd7dbf8fc4222f62a4f06c5b32c3e097de97f5ff48218c8d77676d3424f363" +dependencies = [ + "arbitrary", + "crate-git-revision", + "ethnum", + "num-derive", + "num-traits", + "serde", + "soroban-env-macros", + "soroban-wasmi", + "static_assertions", + "stellar-xdr", + "wasmparser", +] + +[[package]] +name = "soroban-env-guest" +version = "21.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558a69d53d543a4b1ac60681332594dc1417080cffd2a6851bb6e0a376ebc76f" +dependencies = [ + "soroban-env-common", + "static_assertions", +] + +[[package]] +name = "soroban-env-host" +version = "21.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956beee1e959b7b8ac7bea8396454d1534927276830430bf015eafdc756d84ae" +dependencies = [ + "backtrace", + "curve25519-dalek", + "ecdsa", + "ed25519-dalek", + "elliptic-curve", + "generic-array", + "getrandom", + "hex-literal", + "hmac", + "k256", + "num-derive", + "num-integer", + "num-traits", + "p256", + "rand", + "rand_chacha", + "sec1", + "sha2", + "sha3", + "soroban-builtin-sdk-macros", + "soroban-env-common", + "soroban-wasmi", + "static_assertions", + "stellar-strkey", + "wasmparser", +] + +[[package]] +name = "soroban-env-macros" +version = "21.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04b96c8cf73c941ca134eefd00aa5085c4bcae5d534dd3937f4d69b401a838b" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "serde", + "serde_json", + "stellar-xdr", + "syn", +] + +[[package]] +name = "soroban-ledger-snapshot" +version = "21.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e99e474b9faf76142348780651b0129747d004818447a71c44325152d3ec71" +dependencies = [ + "serde", + "serde_json", + "serde_with", + "soroban-env-common", + "soroban-env-host", + "thiserror", +] + +[[package]] +name = "soroban-sdk" +version = "21.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056d762146fba4d5c0798920484f0120526b3e019b021e6efff6ad7dd62cdcbb" +dependencies = [ + "arbitrary", + "bytes-lit", + "ctor", + "ed25519-dalek", + "rand", + "serde", + "serde_json", + "soroban-env-guest", + "soroban-env-host", + "soroban-ledger-snapshot", + "soroban-sdk-macros", + "stellar-strkey", +] + +[[package]] +name = "soroban-sdk-macros" +version = "21.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7d4d78936704cc2e686e1bb77fb5e9075adc392756aea74a3eb47aab74dd7e" +dependencies = [ + "crate-git-revision", + "darling", + "itertools", + "proc-macro2", + "quote", + "rustc_version", + "sha2", + "soroban-env-common", + "soroban-spec", + "soroban-spec-rust", + "stellar-xdr", + "syn", +] + +[[package]] +name = "soroban-spec" +version = "21.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5c72bb3677167ba79c8f0f307b3a5b6469c40fd3ff01599298b3eff5c3f6e19" +dependencies = [ + "base64 0.13.1", + "stellar-xdr", + "thiserror", + "wasmparser", +] + +[[package]] +name = "soroban-spec-rust" +version = "21.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6ca7570c91f2a54120269e6a7edb2f968b1661c54d0faca40b0f727fbc24b7" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "sha2", + "soroban-spec", + "stellar-xdr", + "syn", + "thiserror", +] + +[[package]] +name = "soroban-wasmi" +version = "0.31.1-soroban.20.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710403de32d0e0c35375518cb995d4fc056d0d48966f2e56ea471b8cb8fc9719" +dependencies = [ + "smallvec", + "spin", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stellar-strkey" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12d2bf45e114117ea91d820a846fd1afbe3ba7d717988fee094ce8227a3bf8bd" +dependencies = [ + "base32", + "crate-git-revision", + "thiserror", +] + +[[package]] +name = "stellar-xdr" +version = "21.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec43c9c5ae7ec7b6ac9e263b6d5b9e3781aa05ba3a1c05f6e70701c5c6600665" +dependencies = [ + "arbitrary", + "base64 0.13.1", + "crate-git-revision", + "escape-bytes", + "hex", + "serde", + "serde_with", + "stellar-strkey", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "2.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +dependencies = [ + "time-core", +] + +[[package]] +name = "title" +version = "0.0.1" +dependencies = [ + "soroban-sdk", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" + +[[package]] +name = "wasmi_arena" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "401c1f35e413fac1846d4843745589d9ec678977ab35a384db8ae7830525d468" + +[[package]] +name = "wasmi_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser" +version = "0.116.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" +dependencies = [ + "indexmap 2.1.0", + "semver", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +dependencies = [ + "indexmap-nostd", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/soroban-react-dapp/contracts/title/Cargo.toml b/soroban-react-dapp/contracts/title/Cargo.toml new file mode 100755 index 0000000..c19c2a1 --- /dev/null +++ b/soroban-react-dapp/contracts/title/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "title" +version = "0.0.1" +authors = ["princesoDan"] +license = "Apache-2.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { version = "21.0.1-preview.3"} + +[dev-dependencies] +soroban-sdk = { version = "21.0.1-preview.3",features = ["testutils"] } + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true \ No newline at end of file diff --git a/soroban-react-dapp/contracts/title/Makefile b/soroban-react-dapp/contracts/title/Makefile new file mode 100755 index 0000000..4eb3778 --- /dev/null +++ b/soroban-react-dapp/contracts/title/Makefile @@ -0,0 +1,15 @@ +default: build + +all: test + +test: build + cargo test + +build: + cargo build --target wasm32-unknown-unknown --release + @ls -l target/wasm32-unknown-unknown/release/*.wasm +fmt: + cargo fmt --all --check + +clean: + cargo clean diff --git a/soroban-react-dapp/contracts/title/README.md b/soroban-react-dapp/contracts/title/README.md new file mode 100755 index 0000000..e70fd4f --- /dev/null +++ b/soroban-react-dapp/contracts/title/README.md @@ -0,0 +1,15 @@ +# soroban-examples + +Example contracts for Soroban. + +Follow along with [The Documentation](https://soroban.stellar.org/docs/category/examples). + +Open a development environment on GitPod: + +[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/stellar/soroban-examples) + +WARNING: These implementations have not been tested or audited. They are likely +to have significant errors and security vulnerabilities. They should not be +relied on for any purpose. + +Join us In the [Stellar Developers Discord server](https://discord.gg/stellardev) diff --git a/soroban-react-dapp/contracts/title/greeting.test.ts b/soroban-react-dapp/contracts/title/greeting.test.ts new file mode 100644 index 0000000..29ceca4 --- /dev/null +++ b/soroban-react-dapp/contracts/title/greeting.test.ts @@ -0,0 +1,24 @@ +import { expect } from 'chai'; +import { config } from "../utils/env_config.js"; +import { AddressBook } from "../utils/address_book.js"; +import { deployContract,invokeContract } from "../utils/contract.js"; +import { Keypair } from "@stellar/stellar-sdk"; +const network = "testnet"; //https://horizon-testnet.stellar.org; +const loadFromFile = config(network); +const Mykeys = Keypair.fromSecret(loadFromFile.admin.secret());//Contains accourding keys with. env file +describe('Greeting Contract deployment test', function () { + const addressBook = AddressBook.loadFromFile(network, loadFromFile); + const currentContractHash = addressBook.getContractId("greeting");// + const wasmHash = addressBook.getWasmHash("greeting"); + it('--Confirmation of the deployment on horizon testnet', async function () { + const contractId = await deployContract(currentContractHash, wasmHash, addressBook, Mykeys); + expect(contractId).to.be.a('string'); + expect(contractId).to.have.lengthOf.at.least(2); + expect(contractId).not.to.be.null; + }); + it('--Invoking the contract', async function() { + const contractInfo = await invokeContract(currentContractHash, addressBook, "read_title", [], Mykeys); + expect(contractInfo).to.be.a('object'); + expect(contractInfo.status).to.equal('SUCCESS'); + }); +}); \ No newline at end of file diff --git a/soroban-react-dapp/contracts/title/src/lib.rs b/soroban-react-dapp/contracts/title/src/lib.rs new file mode 100755 index 0000000..099a76d --- /dev/null +++ b/soroban-react-dapp/contracts/title/src/lib.rs @@ -0,0 +1,66 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Symbol, symbol_short, String, Address, Map, contracterror}; + +const ADMIN: Symbol = symbol_short!("ADMIN"); +const TITLE: Symbol = symbol_short!("TITLE"); +const AUTH_USERS: Symbol = symbol_short!("AUTH_USER"); + +#[contract] +pub struct TitleContract; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum ContractError { + NotInitialized = 400, + NotAuthorized = 401, +} + +#[contractimpl] +impl TitleContract { + // Configura el administrador del contrato + pub fn set_admin(env: Env, new_admin: Address) -> Result<(), ContractError> { + if env.storage().instance().has(&ADMIN) { + Err(ContractError::NotInitialized) + } else { + env.storage().instance().set(&ADMIN, &new_admin); + Ok(()) + } + } + + // Agrega una dirección autorizada para modificar el título + pub fn add_user(env: Env, user: Address) { + let admin: Address = env.storage().instance().get(&ADMIN).unwrap(); + admin.require_auth(); + + let mut authorized_users: Map = env.storage().instance().get(&AUTH_USERS).unwrap_or(Map::new(&env)); + authorized_users.set(user, true); + env.storage().instance().set(&AUTH_USERS, &authorized_users); + } + + // Modifica el título si la dirección está autorizada + pub fn modify_title(env: Env, user: Address, new_title: String) -> Result<(), ContractError> { + user.require_auth(); + + let authorized_users: Map = env.storage().instance().get(&AUTH_USERS).unwrap_or(Map::new(&env)); + if authorized_users.get(user.clone()).unwrap_or(false) { + env.storage().instance().set(&TITLE, &new_title); + Ok(()) + } else { + Err(ContractError::NotAuthorized) + } + } + + // Obtiene el título actual + pub fn get_title(env: Env) -> String { + env.storage().instance().get(&TITLE).unwrap_or(String::from_str(&env, "No Title Set")) + } + + // Obtiene la dirección del administrador del contrato + pub fn address_admin(env: Env) -> Result { + match env.storage().instance().get(&ADMIN) { + Some(admin_address) => Ok(admin_address), + None => Err(ContractError::NotInitialized), + } + } +} diff --git a/soroban-react-dapp/contracts/title/src/test.rs b/soroban-react-dapp/contracts/title/src/test.rs new file mode 100755 index 0000000..682ab79 --- /dev/null +++ b/soroban-react-dapp/contracts/title/src/test.rs @@ -0,0 +1,116 @@ +#![cfg(test)] + +use soroban_sdk::{testutils::Address as _, Address, Env, Symbol, Vec, String}; +use crate::{TitleContract, TitleContractClient, ContractError, ADMIN, TITLE, AUTH_USERS}; + +#[test] +fn test_set_admin() { + let env = Env::default(); + let admin = Address::random(&env); + let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + + // Setting the admin + client.set_admin(&admin).unwrap(); + + // Verify the admin was set correctly + assert_eq!(env.storage().instance().get::
(&ADMIN).unwrap(), admin); +} + +#[test] +fn test_add_user() { + let env = Env::default(); + let admin = Address::random(&env); + let user = Address::random(&env); + let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + + // Set the admin + client.set_admin(&admin).unwrap(); + + // Add a user as admin + env.set_authorized(&admin, true); + client.add_user(&user); + + // Verify the user was added + let authorized_users: Vec<(Address, bool)> = env.storage().instance().get(&AUTH_USERS).unwrap().iter().collect(); + assert!(authorized_users.iter().any(|(addr, _)| *addr == user)); +} + +#[test] +fn test_modify_title() { + let env = Env::default(); + let admin = Address::random(&env); + let user = Address::random(&env); + let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + let new_title = String::from_str(&env, "New Title"); + + // Set the admin and add a user + client.set_admin(&admin).unwrap(); + env.set_authorized(&admin, true); + client.add_user(&user); + + // Modify the title as the authorized user + env.set_authorized(&user, true); + client.modify_title(&user, &new_title).unwrap(); + + // Verify the title was modified + assert_eq!(client.get_title(), new_title); +} + +#[test] +fn test_unauthorized_modify_title() { + let env = Env::default(); + let user = Address::random(&env); + let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + let new_title = String::from_str(&env, "New Title"); + + // Attempt to modify title without authorization + env.set_authorized(&user, true); + let result = client.modify_title(&user, &new_title); + + // Verify that the modification failed due to lack of authorization + assert_eq!(result, Err(ContractError::NotAuthorized)); +} + +#[test] +fn test_get_title() { + let env = Env::default(); + let admin = Address::random(&env); + let user = Address::random(&env); + let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + let new_title = String::from_str(&env, "New Title"); + + // Set the admin, add a user, and modify the title + client.set_admin(&admin).unwrap(); + env.set_authorized(&admin, true); + client.add_user(&user); + env.set_authorized(&user, true); + client.modify_title(&user, &new_title).unwrap(); + + // Retrieve and verify the title + assert_eq!(client.get_title(), new_title); +} + +#[test] +fn test_address_admin() { + let env = Env::default(); + let admin = Address::random(&env); + let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + + // Set the admin + client.set_admin(&admin).unwrap(); + + // Verify that the admin address is returned correctly + assert_eq!(client.address_admin().unwrap(), admin); +} + +#[test] +fn test_address_admin_not_initialized() { + let env = Env::default(); + let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + + // Attempt to retrieve admin address without setting it + let result = client.address_admin(); + + // Verify that an error is returned due to the admin not being initialized + assert_eq!(result, Err(ContractError::NotInitialized)); +} diff --git a/soroban-react-dapp/contracts/utils/contract.ts b/soroban-react-dapp/contracts/utils/contract.ts index fe3257b..337861c 100644 --- a/soroban-react-dapp/contracts/utils/contract.ts +++ b/soroban-react-dapp/contracts/utils/contract.ts @@ -85,7 +85,8 @@ export async function invokeContract( addressBook: AddressBook, method: string, params: xdr.ScVal[], - source: Keypair + source: Keypair, + sim: boolean = false, ) { console.log("Invoking contract: ", contractKey, " with method: ", method); const contractAddress = addressBook.getContractId(contractKey); @@ -95,7 +96,7 @@ export async function invokeContract( return await invoke( contractOperation, source, - false, + sim, ); } diff --git a/soroban-react-dapp/src/components/web3/ManageTitle.tsx b/soroban-react-dapp/src/components/web3/ManageTitle.tsx new file mode 100644 index 0000000..8630a84 --- /dev/null +++ b/soroban-react-dapp/src/components/web3/ManageTitle.tsx @@ -0,0 +1,138 @@ +import { Box, Button, Card, FormControl, FormLabel, Input, Text, VStack } from '@chakra-ui/react'; +import { type FC, useState, useEffect, useCallback } from 'react'; +import toast from 'react-hot-toast'; +import 'twin.macro'; + +import { useSorobanReact } from "@soroban-react/core"; +import * as StellarSdk from '@stellar/stellar-sdk'; + +import { contractInvoke, useRegisteredContract } from '@soroban-react/contracts'; +import { Address, nativeToScVal, xdr } from '@stellar/stellar-sdk'; + +export const ManageTitle: FC = () => { + const sorobanContext = useSorobanReact(); + const { activeChain, server, address } = sorobanContext; // Aquí se obtiene la dirección del contexto + + const [currentTitle, setCurrentTitle] = useState(''); + const [adminAddress, setAdminAddress] = useState(''); + const [newTitle, setNewTitle] = useState(''); + const [newUser, setNewUser] = useState(''); + const [isLoading, setIsLoading] = useState(false); + + const contract = useRegisteredContract("title"); + + const fetchTitle = useCallback(async () => { + if (!server || !contract) return; + + try { + const result = await contract.invoke({ + method: "get_title", + signAndSend: false + }); + const title = StellarSdk.scValToNative(result as xdr.ScVal) as string; + setCurrentTitle(title); + } catch (error) { + console.error("Error fetching title:", error); + toast.error('Error fetching title.'); + } + }, [server, contract]); + + const fetchAdminAddress = useCallback(async () => { + if (!server || !contract) return; + + try { + const result = await contract.invoke({ + method: "address_admin", + signAndSend: false + }); + const admin = StellarSdk.scValToNative(result as xdr.ScVal) as string; + setAdminAddress(admin); + } catch (error) { + console.error("Error fetching admin address:", error); + toast.error('Error fetching admin address.'); + } + }, [server, contract]); + + useEffect(() => { + fetchTitle(); + fetchAdminAddress(); + }, [fetchTitle, fetchAdminAddress]); + + const modifyTitle = async () => { + if (!newTitle) { + toast.error('Please enter a new title.'); + return; + } + if (!server || !contract || !address) return; // Verificamos que la dirección esté definida + + setIsLoading(true); + try { + await contractInvoke({ + contractAddress: contract.deploymentInfo.contractAddress, + method: "modify_title", + args: [new Address(address).toScVal(), nativeToScVal(newTitle, { type: "string" })], + signAndSend: true, + sorobanContext + }); + toast.success("Title modified."); + setCurrentTitle(newTitle); + } catch (error) { + console.error("Error modifying title:", error); + toast.error('User not authorized.'); + } finally { + setIsLoading(false); + } + }; + + const addUser = async () => { + if (!newUser) { + toast.error('Please enter a new user address.'); + return; + } + if (!server || !contract || !address) return; // También verificamos que la dirección esté definida + + setIsLoading(true); + try { + await contractInvoke({ + contractAddress: contract.deploymentInfo.contractAddress, + method: "add_user", + args: [new Address(newUser).toScVal()], + signAndSend: true, + sorobanContext + }); + toast.success("User added."); + } catch (error) { + console.error("Error adding user:", error); + toast.error('You are not the admin, you are not authorized for this.'); + } finally { + setIsLoading(false); + } + }; + + return ( + + + Current Title + {currentTitle || "No Title Set"} + + + Admin Address + {adminAddress || "No Admin Set"} + + + New Title + setNewTitle(e.target.value)} /> + + + + New User Address + setNewUser(e.target.value)} /> + + + + ); +}; diff --git a/soroban-react-dapp/src/pages/index.tsx b/soroban-react-dapp/src/pages/index.tsx index f23437f..3f70644 100644 --- a/soroban-react-dapp/src/pages/index.tsx +++ b/soroban-react-dapp/src/pages/index.tsx @@ -3,6 +3,7 @@ import { CenterBody } from '@/components/layout/CenterBody' import { ChainInfo } from '@/components/web3/ChainInfo' import { ConnectButton } from '@/components/web3/ConnectButton' import { GreeterContractInteractions } from '@/components/web3/GreeterContractInteractions' +import { ManageTitle } from '@/components/web3/ManageTitle' import type { NextPage } from 'next' import 'twin.macro' @@ -31,7 +32,7 @@ const HomePage: NextPage = () => { {/* Greeter Read/Write Contract Interactions */} - + diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..803a9a0 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,476 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@inquirer/figures@^1.0.3": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.5.tgz#57f9a996d64d3e3345d2a3ca04d36912e94f8790" + integrity sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA== + +"@types/node@^20.8.10": + version "20.16.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.16.1.tgz#0b44b15271d0e2191ca68faf1fbe506e06aed732" + integrity sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ== + dependencies: + undici-types "~6.19.2" + +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +execa@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + +external-editor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +fs-extra@^11.1.1: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inquirer@^9.2.11: + version "9.3.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-9.3.6.tgz#670f1e9408743c3ed23df576f94fe5369f353055" + integrity sha512-riK/iQB2ctwkpWYgjjWIRv3MBLt2gzb2Sj0JNQNbyTXgyXsLWcDPJ5WS5ZDTCx7BRFnJsARtYh+58fjP5M2Y0Q== + dependencies: + "@inquirer/figures" "^1.0.3" + ansi-escapes "^4.3.2" + cli-width "^4.1.0" + external-editor "^3.1.0" + mute-stream "1.0.0" + ora "^5.4.1" + run-async "^3.0.0" + rxjs "^7.8.1" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +mute-stream@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + +npm-run-path@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" + integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== + dependencies: + path-key "^4.0.0" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +run-async@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-3.0.0.tgz#42a432f6d76c689522058984384df28be379daad" + integrity sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q== + +rxjs@^7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +string-width@^4.1.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tslib@^2.1.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +yoctocolors-cjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== From eb5665ecbe54dec4f70e0186f87a36f77d721403 Mon Sep 17 00:00:00 2001 From: "daniel.andrade1991@gmail.com" Date: Tue, 27 Aug 2024 15:45:45 -0400 Subject: [PATCH 2/5] improve_challenge_title --- soroban-react-dapp/README.md | 4 +- soroban-react-dapp/contracts/deployments.json | 2 +- .../contracts/scripts/test_title.ts | 126 +++++++++++++----- soroban-react-dapp/contracts/title/src/lib.rs | 31 ++++- .../contracts/title/src/test.rs | 121 +++++------------ .../src/components/web3/ManageTitle.tsx | 81 ++++++++++- .../web3/MySorobanReactProvider.tsx | 2 +- 7 files changed, 234 insertions(+), 133 deletions(-) diff --git a/soroban-react-dapp/README.md b/soroban-react-dapp/README.md index b6bc803..6039400 100644 --- a/soroban-react-dapp/README.md +++ b/soroban-react-dapp/README.md @@ -7,8 +7,8 @@ Hello and welcome to Title Contract! 🎉 Title is a special wallet containing the following crucial data: Account Admin: - Public Key: GA4HKU3GDGZHSUOAW6X3NQHG36EX4M5Z7THNWVXJA6GKTDHOI27OKUGI - Secret Key: SDDWPQWJFO7UGGFUBOZ4HZJDPBA62MWY3NUK7QTRL2LOTUVT5J3CRY7H + Public Key: GAMPJTSVJSEVX4KKWVY2G7JM66AI6PPQIZMTW2EI6ZVJLEZLMKI7GAFK + Secret Key: SCHWRT7BOMNJPOZECVKWZND2XFMEGVVJ4ILZEPFQIRTCYVPGCGKKFAIA This contract is the guardian that decides who can change the character associated with the wallet. Only those who know "the magic trick" will have that power. 🛠️ Project Setup diff --git a/soroban-react-dapp/contracts/deployments.json b/soroban-react-dapp/contracts/deployments.json index 2e81167..5d131fc 100644 --- a/soroban-react-dapp/contracts/deployments.json +++ b/soroban-react-dapp/contracts/deployments.json @@ -12,6 +12,6 @@ { "contractId": "title", "networkPassphrase": "Test SDF Network ; September 2015", - "contractAddress": "CD2K6QRWVSTH5C2JPO455BNKS5WOOH5PVBP5SQS2TLDYZFQYZSNDJJAH" + "contractAddress": "CAS3V3WZFZYQMHFXRJJOCYT2JMLO6CFZSIQK64NN4WR3WN4OB5TXV3XL" } ] \ No newline at end of file diff --git a/soroban-react-dapp/contracts/scripts/test_title.ts b/soroban-react-dapp/contracts/scripts/test_title.ts index 2759867..c82626b 100644 --- a/soroban-react-dapp/contracts/scripts/test_title.ts +++ b/soroban-react-dapp/contracts/scripts/test_title.ts @@ -11,37 +11,39 @@ export async function testTitleContract(addressBook: AddressBook) { const admin = loadedConfig.admin; const user_1 = loadedConfig.getUser("USER_1"); const user_2 = loadedConfig.getUser("USER_2"); + const new_admin = loadedConfig.getUser("NEW_ADMIN"); if (network !== "mainnet") { await airdropAccount(admin); await airdropAccount(user_1); await airdropAccount(user_2); + await airdropAccount(new_admin); } - //Set admin - // console.log('-------------------------------------------------------'); - // console.log('Setting Admin'); - // console.log('-------------------------------------------------------'); + // Set admin + console.log('-------------------------------------------------------'); + console.log('Setting Admin'); + console.log('-------------------------------------------------------'); - // const params_set_admin: xdr.ScVal[] = [ - // new Address(admin.publicKey()).toScVal(), - // ]; + const params_set_admin = [ + new Address(admin.publicKey()).toScVal(), + ]; - // const result_set_admin = await invokeContract( - // 'title', - // addressBook, - // 'set_admin', - // params_set_admin, - // admin - // ); - // console.log("Result of set_admin: ", result_set_admin); + const result_set_admin = await invokeContract( + 'title', + addressBook, + 'set_admin', + params_set_admin, + admin + ); + console.log("Result of set_admin: ", result_set_admin); // Add user console.log('-------------------------------------------------------'); console.log('Adding User'); console.log('-------------------------------------------------------'); - const params_add_user: xdr.ScVal[] = [ + const params_add_user = [ new Address(user_1.publicKey()).toScVal(), ]; @@ -54,14 +56,14 @@ export async function testTitleContract(addressBook: AddressBook) { ); console.log("Result of add_user: ", result_add_user); - // Attempt to modify title with authorized user + // Modify title with authorized user console.log('-------------------------------------------------------'); console.log('Modifying Title with Authorized User'); console.log('-------------------------------------------------------'); - const params_modify_title: xdr.ScVal[] = [ + const params_modify_title = [ new Address(user_1.publicKey()).toScVal(), - nativeToScVal("New Title", { type: "string" }) + nativeToScVal("PrincesitoDan", { type: "string" }) ]; const result_modify_title = await invokeContract( @@ -92,16 +94,14 @@ export async function testTitleContract(addressBook: AddressBook) { console.error("Error: Unable to retrieve title, result is undefined or invalid."); } - console.log("Title after modification: ", scValToNative(result_get_title.result.retval)); - // Attempt to modify title with unauthorized user console.log('-------------------------------------------------------'); console.log('Modifying Title with Unauthorized User'); console.log('-------------------------------------------------------'); - const params_modify_title_unauthorized: xdr.ScVal[] = [ + const params_modify_title_unauthorized = [ new Address(user_2.publicKey()).toScVal(), - nativeToScVal("New Title", { type: "string" }) + nativeToScVal("New Title Unauthorized", { type: "string" }) ]; try { @@ -114,24 +114,88 @@ export async function testTitleContract(addressBook: AddressBook) { ); console.log("Unexpected success in unauthorized modify_title: ", result_modify_title_unauthorized); } catch (e) { - const error = e as Error; - console.log("Expected failure in unauthorized modify_title: ", error.message); + const error = e; + console.log("Expected failure in unauthorized modify_title: ", error); } - // Get admin address + // Modify admin + console.log('-------------------------------------------------------'); + console.log('Modifying Admin'); + console.log('-------------------------------------------------------'); + + const params_modify_admin = [ + new Address(new_admin.publicKey()).toScVal(), + ]; + + const result_modify_admin = await invokeContract( + 'title', + addressBook, + 'modify_admin', + params_modify_admin, + admin // Current admin makes the change + ); + console.log("Result of modify_admin: ", result_modify_admin); + + // Add new user by new admin + console.log('-------------------------------------------------------'); + console.log('Adding User by New Admin'); + console.log('-------------------------------------------------------'); + + const params_add_user_by_new_admin = [ + new Address(user_2.publicKey()).toScVal(), + ]; + + const result_add_user_by_new_admin = await invokeContract( + 'title', + addressBook, + 'add_user', + params_add_user_by_new_admin, + new_admin // The new admin adds the user + ); + console.log("Result of add_user_by_new_admin: ", result_add_user_by_new_admin); + + // Get users list console.log('-------------------------------------------------------'); - console.log('Getting Admin Address'); + console.log('Getting List of Authorized Users'); console.log('-------------------------------------------------------'); - const result_address_admin = await invokeContract( + const result_get_users = await invokeContract( 'title', addressBook, - 'address_admin', + 'get_users', [], - admin, // Admin should be able to get the address + new_admin, // New admin retrieves the list of users true ); - console.log("Admin address: ", scValToNative(result_address_admin.result.retval)); + if (result_get_users && result_get_users.result && result_get_users.result.retval) { + const users = scValToNative(result_get_users.result.retval); + console.log("Authorized users: ", users); + } else { + console.error("Error: Unable to retrieve users, result is undefined or invalid."); + } + + // Attempt to add a user by the initial admin (should fail) + console.log('-------------------------------------------------------'); + console.log('Attempting to Add User by Initial Admin (Should Fail)'); + console.log('-------------------------------------------------------'); + + const params_add_user_by_initial_admin = [ + new Address(user_2.publicKey()).toScVal(), + ]; + + try { + const result_add_user_by_initial_admin = await invokeContract( + 'title', + addressBook, + 'add_user', + params_add_user_by_initial_admin, + admin // Initial admin attempts to add the user + ); + console.log("Unexpected success in add_user by initial admin: ", result_add_user_by_initial_admin); + } catch (e) { + const error = e; + console.log("Expected failure in add_user by initial admin: ", error); + } } const network = process.argv[2]; diff --git a/soroban-react-dapp/contracts/title/src/lib.rs b/soroban-react-dapp/contracts/title/src/lib.rs index 099a76d..f69d2d0 100755 --- a/soroban-react-dapp/contracts/title/src/lib.rs +++ b/soroban-react-dapp/contracts/title/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, Env, Symbol, symbol_short, String, Address, Map, contracterror}; +use soroban_sdk::{contract, contractimpl, Env, Symbol, symbol_short, String, Address, Map, Vec, contracterror}; const ADMIN: Symbol = symbol_short!("ADMIN"); const TITLE: Symbol = symbol_short!("TITLE"); @@ -18,7 +18,7 @@ pub enum ContractError { #[contractimpl] impl TitleContract { - // Configura el administrador del contrato + // Sets the contract's administrator pub fn set_admin(env: Env, new_admin: Address) -> Result<(), ContractError> { if env.storage().instance().has(&ADMIN) { Err(ContractError::NotInitialized) @@ -28,7 +28,7 @@ impl TitleContract { } } - // Agrega una dirección autorizada para modificar el título + // Adds an authorized address to modify the title pub fn add_user(env: Env, user: Address) { let admin: Address = env.storage().instance().get(&ADMIN).unwrap(); admin.require_auth(); @@ -38,7 +38,7 @@ impl TitleContract { env.storage().instance().set(&AUTH_USERS, &authorized_users); } - // Modifica el título si la dirección está autorizada + // Modifies the title if the address is authorized pub fn modify_title(env: Env, user: Address, new_title: String) -> Result<(), ContractError> { user.require_auth(); @@ -51,16 +51,35 @@ impl TitleContract { } } - // Obtiene el título actual + // Retrieves the current title pub fn get_title(env: Env) -> String { env.storage().instance().get(&TITLE).unwrap_or(String::from_str(&env, "No Title Set")) } - // Obtiene la dirección del administrador del contrato + // Retrieves the contract's administrator address pub fn address_admin(env: Env) -> Result { match env.storage().instance().get(&ADMIN) { Some(admin_address) => Ok(admin_address), None => Err(ContractError::NotInitialized), } } + + // Retrieves the authorized users who can modify the title + pub fn get_users(env: Env) -> Vec
{ + let authorized_users: Map = env.storage().instance().get(&AUTH_USERS).unwrap_or(Map::new(&env)); + let mut users = Vec::new(&env); + for user in authorized_users.keys() { + users.append(&mut Vec::from_slice(&env, &[user])); + } + users + } + + // Allows the current admin to transfer admin rights to a new address + pub fn modify_admin(env: Env, new_admin: Address) -> Result<(), ContractError> { + let admin: Address = env.storage().instance().get(&ADMIN).unwrap(); + admin.require_auth(); + + env.storage().instance().set(&ADMIN, &new_admin); + Ok(()) + } } diff --git a/soroban-react-dapp/contracts/title/src/test.rs b/soroban-react-dapp/contracts/title/src/test.rs index 682ab79..edea02a 100755 --- a/soroban-react-dapp/contracts/title/src/test.rs +++ b/soroban-react-dapp/contracts/title/src/test.rs @@ -1,116 +1,63 @@ #![cfg(test)] -use soroban_sdk::{testutils::Address as _, Address, Env, Symbol, Vec, String}; -use crate::{TitleContract, TitleContractClient, ContractError, ADMIN, TITLE, AUTH_USERS}; +use super::*; +use soroban_sdk::{Env, testutils::{Address as TestAddress, Vec as TestVec}, Symbol, String}; #[test] fn test_set_admin() { let env = Env::default(); - let admin = Address::random(&env); - let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + let admin = TestAddress::random(&env); - // Setting the admin - client.set_admin(&admin).unwrap(); + // Attempt to set the admin when it has not been initialized yet + assert!(TitleContract::set_admin(env.clone(), admin.clone()).is_ok()); - // Verify the admin was set correctly - assert_eq!(env.storage().instance().get::
(&ADMIN).unwrap(), admin); + // Attempt to set the admin again should fail + assert_eq!( + TitleContract::set_admin(env.clone(), admin.clone()).unwrap_err(), + ContractError::NotInitialized + ); } #[test] -fn test_add_user() { +fn test_add_user_and_get_users() { let env = Env::default(); - let admin = Address::random(&env); - let user = Address::random(&env); - let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + let admin = TestAddress::random(&env); + let user = TestAddress::random(&env); - // Set the admin - client.set_admin(&admin).unwrap(); + TitleContract::set_admin(env.clone(), admin.clone()).unwrap(); + TitleContract::add_user(env.clone(), user.clone()); - // Add a user as admin - env.set_authorized(&admin, true); - client.add_user(&user); - - // Verify the user was added - let authorized_users: Vec<(Address, bool)> = env.storage().instance().get(&AUTH_USERS).unwrap().iter().collect(); - assert!(authorized_users.iter().any(|(addr, _)| *addr == user)); + // Verify that the user appears in the list of authorized users + let users = TitleContract::get_users(env.clone()); + assert_eq!(users.contains(&user), true); } #[test] fn test_modify_title() { let env = Env::default(); - let admin = Address::random(&env); - let user = Address::random(&env); - let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); - let new_title = String::from_str(&env, "New Title"); - - // Set the admin and add a user - client.set_admin(&admin).unwrap(); - env.set_authorized(&admin, true); - client.add_user(&user); - - // Modify the title as the authorized user - env.set_authorized(&user, true); - client.modify_title(&user, &new_title).unwrap(); - - // Verify the title was modified - assert_eq!(client.get_title(), new_title); -} - -#[test] -fn test_unauthorized_modify_title() { - let env = Env::default(); - let user = Address::random(&env); - let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); - let new_title = String::from_str(&env, "New Title"); + let admin = TestAddress::random(&env); + let user = TestAddress::random(&env); + let new_title = String::from_str(&env, "PrincesitoDan"); - // Attempt to modify title without authorization - env.set_authorized(&user, true); - let result = client.modify_title(&user, &new_title); - - // Verify that the modification failed due to lack of authorization - assert_eq!(result, Err(ContractError::NotAuthorized)); -} - -#[test] -fn test_get_title() { - let env = Env::default(); - let admin = Address::random(&env); - let user = Address::random(&env); - let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); - let new_title = String::from_str(&env, "New Title"); - - // Set the admin, add a user, and modify the title - client.set_admin(&admin).unwrap(); - env.set_authorized(&admin, true); - client.add_user(&user); - env.set_authorized(&user, true); - client.modify_title(&user, &new_title).unwrap(); - - // Retrieve and verify the title - assert_eq!(client.get_title(), new_title); -} - -#[test] -fn test_address_admin() { - let env = Env::default(); - let admin = Address::random(&env); - let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + TitleContract::set_admin(env.clone(), admin.clone()).unwrap(); + TitleContract::add_user(env.clone(), user.clone()); - // Set the admin - client.set_admin(&admin).unwrap(); + // Attempt to modify the title by the authorized user + assert!(TitleContract::modify_title(env.clone(), user.clone(), new_title.clone()).is_ok()); - // Verify that the admin address is returned correctly - assert_eq!(client.address_admin().unwrap(), admin); + // Verify that the title was modified + assert_eq!(TitleContract::get_title(env.clone()), new_title); } #[test] -fn test_address_admin_not_initialized() { +fn test_modify_admin() { let env = Env::default(); - let client = TitleContractClient::new(&env, &env.register_contract(None, TitleContract)); + let admin = TestAddress::random(&env); + let new_admin = TestAddress::random(&env); - // Attempt to retrieve admin address without setting it - let result = client.address_admin(); + TitleContract::set_admin(env.clone(), admin.clone()).unwrap(); + TitleContract::modify_admin(env.clone(), new_admin.clone()).unwrap(); - // Verify that an error is returned due to the admin not being initialized - assert_eq!(result, Err(ContractError::NotInitialized)); + // Verify that only the new admin has the necessary permissions + assert_eq!(TitleContract::address_admin(env.clone()).unwrap(), new_admin); } diff --git a/soroban-react-dapp/src/components/web3/ManageTitle.tsx b/soroban-react-dapp/src/components/web3/ManageTitle.tsx index 8630a84..592ed3d 100644 --- a/soroban-react-dapp/src/components/web3/ManageTitle.tsx +++ b/soroban-react-dapp/src/components/web3/ManageTitle.tsx @@ -11,14 +11,16 @@ import { Address, nativeToScVal, xdr } from '@stellar/stellar-sdk'; export const ManageTitle: FC = () => { const sorobanContext = useSorobanReact(); - const { activeChain, server, address } = sorobanContext; // Aquí se obtiene la dirección del contexto + const { activeChain, server, address } = sorobanContext; const [currentTitle, setCurrentTitle] = useState(''); const [adminAddress, setAdminAddress] = useState(''); const [newTitle, setNewTitle] = useState(''); const [newUser, setNewUser] = useState(''); + const [newAdmin, setNewAdmin] = useState(''); + const [authorizedUsers, setAuthorizedUsers] = useState([]); const [isLoading, setIsLoading] = useState(false); - + const contract = useRegisteredContract("title"); const fetchTitle = useCallback(async () => { @@ -53,17 +55,34 @@ export const ManageTitle: FC = () => { } }, [server, contract]); + const fetchAuthorizedUsers = useCallback(async () => { + if (!server || !contract) return; + + try { + const result = await contract.invoke({ + method: "get_users", + signAndSend: false + }); + const users = StellarSdk.scValToNative(result as xdr.ScVal) as string[]; + setAuthorizedUsers(users); + } catch (error) { + console.error("Error fetching authorized users:", error); + toast.error('Error fetching authorized users.'); + } + }, [server, contract]); + useEffect(() => { fetchTitle(); fetchAdminAddress(); - }, [fetchTitle, fetchAdminAddress]); + fetchAuthorizedUsers(); + }, [fetchTitle, fetchAdminAddress, fetchAuthorizedUsers]); const modifyTitle = async () => { if (!newTitle) { toast.error('Please enter a new title.'); return; } - if (!server || !contract || !address) return; // Verificamos que la dirección esté definida + if (!server || !contract || !address) return; setIsLoading(true); try { @@ -76,6 +95,7 @@ export const ManageTitle: FC = () => { }); toast.success("Title modified."); setCurrentTitle(newTitle); + setNewTitle(''); // Limpiar campo de entrada } catch (error) { console.error("Error modifying title:", error); toast.error('User not authorized.'); @@ -89,7 +109,7 @@ export const ManageTitle: FC = () => { toast.error('Please enter a new user address.'); return; } - if (!server || !contract || !address) return; // También verificamos que la dirección esté definida + if (!server || !contract || !address) return; setIsLoading(true); try { @@ -101,6 +121,7 @@ export const ManageTitle: FC = () => { sorobanContext }); toast.success("User added."); + setNewUser(''); // Limpiar campo de entrada } catch (error) { console.error("Error adding user:", error); toast.error('You are not the admin, you are not authorized for this.'); @@ -109,16 +130,56 @@ export const ManageTitle: FC = () => { } }; + const modifyAdmin = async () => { + if (!newAdmin) { + toast.error('Please enter a new admin address.'); + return; + } + if (!server || !contract || !address) return; + + setIsLoading(true); + try { + await contractInvoke({ + contractAddress: contract.deploymentInfo.contractAddress, + method: "modify_admin", + args: [new Address(newAdmin).toScVal()], + signAndSend: true, + sorobanContext + }); + toast.success("Admin modified."); + setAdminAddress(newAdmin); + setNewAdmin(''); // Limpiar campo de entrada + } catch (error) { + console.error("Error modifying admin:", error); + toast.error('You are not authorized for this.'); + } finally { + setIsLoading(false); + } + }; + return ( Current Title {currentTitle || "No Title Set"} + + + Authorized Users + + {authorizedUsers.length > 0 ? ( + authorizedUsers.map((user, idx) => {user}) + ) : ( + No Authorized Users + )} + + + Admin Address {adminAddress || "No Admin Set"} + New Title setNewTitle(e.target.value)} /> @@ -126,6 +187,7 @@ export const ManageTitle: FC = () => { Modify Title + New User Address setNewUser(e.target.value)} /> @@ -133,6 +195,15 @@ export const ManageTitle: FC = () => { Add User + + + New Admin Address + setNewAdmin(e.target.value)} /> + + ); }; + diff --git a/soroban-react-dapp/src/components/web3/MySorobanReactProvider.tsx b/soroban-react-dapp/src/components/web3/MySorobanReactProvider.tsx index 15d557c..5f941a1 100644 --- a/soroban-react-dapp/src/components/web3/MySorobanReactProvider.tsx +++ b/soroban-react-dapp/src/components/web3/MySorobanReactProvider.tsx @@ -10,7 +10,7 @@ import { lobstr } from '@soroban-react/lobstr'; import deployments from '../../../contracts/deployments.json'; const chains: ChainMetadata[] = [sandbox, standalone, futurenet,testnet]; -const connectors: Connector[] = [freighter(), xbull(), hana(), lobstr()]; +const connectors: Connector[] = [freighter(),xbull(), hana(), lobstr()]; export default function MySorobanReactProvider({children}:{children: React.ReactNode}) { From b744aafef841f54e325ef210a8f425e83faa9b3c Mon Sep 17 00:00:00 2001 From: "daniel.andrade1991@gmail.com" Date: Mon, 2 Sep 2024 19:57:29 -0400 Subject: [PATCH 3/5] fix title.rs and test.rs --- soroban-react-dapp/contracts/title/src/lib.rs | 69 +- .../contracts/title/src/test.rs | 164 ++++- .../test_snapshots/test/test_add_user.1.json | 427 +++++++++++ .../test/test_add_user_and_get_users.1.json | 427 +++++++++++ .../test/test_auth_control.1.json | 124 ++++ .../test/test_modify_admin.1.json | 406 +++++++++++ .../test/test_modify_title.1.json | 670 ++++++++++++++++++ .../test_snapshots/test/test_set_admin.1.json | 212 ++++++ 8 files changed, 2444 insertions(+), 55 deletions(-) create mode 100644 soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user.1.json create mode 100644 soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user_and_get_users.1.json create mode 100644 soroban-react-dapp/contracts/title/test_snapshots/test/test_auth_control.1.json create mode 100644 soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_admin.1.json create mode 100644 soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_title.1.json create mode 100644 soroban-react-dapp/contracts/title/test_snapshots/test/test_set_admin.1.json diff --git a/soroban-react-dapp/contracts/title/src/lib.rs b/soroban-react-dapp/contracts/title/src/lib.rs index f69d2d0..cd5b9a4 100755 --- a/soroban-react-dapp/contracts/title/src/lib.rs +++ b/soroban-react-dapp/contracts/title/src/lib.rs @@ -12,38 +12,50 @@ pub struct TitleContract; #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[repr(u32)] pub enum ContractError { - NotInitialized = 400, - NotAuthorized = 401, + NotInitialized = 400, // Error if contract is not initialized + NotAuthorized = 401, // Error if the user is not authorized } #[contractimpl] impl TitleContract { - // Sets the contract's administrator + // Sets the admin for the contract. Can only be called once. pub fn set_admin(env: Env, new_admin: Address) -> Result<(), ContractError> { + // Check if admin is already set; if yes, return an error if env.storage().instance().has(&ADMIN) { - Err(ContractError::NotInitialized) - } else { - env.storage().instance().set(&ADMIN, &new_admin); - Ok(()) + return Err(ContractError::NotInitialized); } + // Set the new admin address in the storage + env.storage().instance().set(&ADMIN, &new_admin); + Ok(()) } - // Adds an authorized address to modify the title - pub fn add_user(env: Env, user: Address) { - let admin: Address = env.storage().instance().get(&ADMIN).unwrap(); + // Adds a new user to the list of authorized users. Only callable by the admin. + pub fn add_user(env: Env, user: Address) -> Result<(), ContractError> { + // Fetch the current admin from storage + let admin = env.storage().instance().get::(&ADMIN) + .ok_or(ContractError::NotInitialized)?; + // Ensure the caller is the admin admin.require_auth(); - let mut authorized_users: Map = env.storage().instance().get(&AUTH_USERS).unwrap_or(Map::new(&env)); + // Get the list of authorized users or initialize it if it doesn't exist + let mut authorized_users: Map = env.storage().instance().get::>(&AUTH_USERS).unwrap_or(Map::new(&env)); + // Add the new user to the list authorized_users.set(user, true); + // Save the updated list back to storage env.storage().instance().set(&AUTH_USERS, &authorized_users); + Ok(()) } - // Modifies the title if the address is authorized + // Modifies the title. Only authorized users can call this. pub fn modify_title(env: Env, user: Address, new_title: String) -> Result<(), ContractError> { + // Ensure the caller is the user who is trying to modify the title user.require_auth(); - let authorized_users: Map = env.storage().instance().get(&AUTH_USERS).unwrap_or(Map::new(&env)); - if authorized_users.get(user.clone()).unwrap_or(false) { + // Fetch the list of authorized users from storage + let authorized_users: Map = env.storage().instance().get::>(&AUTH_USERS).unwrap_or(Map::new(&env)); + // Check if the user is authorized + if let Some(true) = authorized_users.get(user.clone()) { + // Set the new title in storage env.storage().instance().set(&TITLE, &new_title); Ok(()) } else { @@ -51,35 +63,42 @@ impl TitleContract { } } - // Retrieves the current title + // Retrieves the current title. If not set, returns "No Title Set". pub fn get_title(env: Env) -> String { - env.storage().instance().get(&TITLE).unwrap_or(String::from_str(&env, "No Title Set")) + // Fetch the title from storage or return a default message + env.storage().instance().get::(&TITLE).unwrap_or(String::from_str(&env, "No Title Set")) } - // Retrieves the contract's administrator address + // Retrieves the current admin address. pub fn address_admin(env: Env) -> Result { - match env.storage().instance().get(&ADMIN) { - Some(admin_address) => Ok(admin_address), - None => Err(ContractError::NotInitialized), - } + // Fetch the admin from storage or return an error if not initialized + env.storage().instance().get::(&ADMIN).ok_or(ContractError::NotInitialized) } - // Retrieves the authorized users who can modify the title + // Retrieves a list of all authorized users. pub fn get_users(env: Env) -> Vec
{ - let authorized_users: Map = env.storage().instance().get(&AUTH_USERS).unwrap_or(Map::new(&env)); + // Fetch the list of authorized users from storage + let authorized_users: Map = env.storage().instance().get::>(&AUTH_USERS).unwrap_or(Map::new(&env)); let mut users = Vec::new(&env); + // Collect all user addresses into a Vec for user in authorized_users.keys() { users.append(&mut Vec::from_slice(&env, &[user])); } users } - // Allows the current admin to transfer admin rights to a new address + // Changes the admin address. Only the current admin can call this. pub fn modify_admin(env: Env, new_admin: Address) -> Result<(), ContractError> { - let admin: Address = env.storage().instance().get(&ADMIN).unwrap(); + // Fetch the current admin from storage + let admin = env.storage().instance().get::(&ADMIN) + .ok_or(ContractError::NotInitialized)?; + // Ensure the caller is the current admin admin.require_auth(); + // Set the new admin address in storage env.storage().instance().set(&ADMIN, &new_admin); Ok(()) } } + +mod test; diff --git a/soroban-react-dapp/contracts/title/src/test.rs b/soroban-react-dapp/contracts/title/src/test.rs index edea02a..b96012c 100755 --- a/soroban-react-dapp/contracts/title/src/test.rs +++ b/soroban-react-dapp/contracts/title/src/test.rs @@ -1,63 +1,167 @@ #![cfg(test)] use super::*; -use soroban_sdk::{Env, testutils::{Address as TestAddress, Vec as TestVec}, Symbol, String}; +use soroban_sdk::{testutils::{Address as _, MockAuth, MockAuthInvoke}, Address, Env, String, IntoVal, Vec, Val}; #[test] fn test_set_admin() { let env = Env::default(); - let admin = TestAddress::random(&env); + let contract_id = env.register_contract(None, TitleContract); + let client = TitleContractClient::new(&env, &contract_id); + + // Crear un usuario virtual para el admin + let admin = Address::generate(&env); + + // Autenticar y setear al admin + client.mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "set_admin", + args: (&admin,).into_val(&env), + sub_invokes: &[], + }, + }]) + .set_admin(&admin); + + // Obtener el admin + assert_eq!(client.address_admin(), admin); - // Attempt to set the admin when it has not been initialized yet - assert!(TitleContract::set_admin(env.clone(), admin.clone()).is_ok()); - // Attempt to set the admin again should fail - assert_eq!( - TitleContract::set_admin(env.clone(), admin.clone()).unwrap_err(), - ContractError::NotInitialized - ); } #[test] fn test_add_user_and_get_users() { let env = Env::default(); - let admin = TestAddress::random(&env); - let user = TestAddress::random(&env); + let contract_id = env.register_contract(None, TitleContract); + let client = TitleContractClient::new(&env, &contract_id); - TitleContract::set_admin(env.clone(), admin.clone()).unwrap(); - TitleContract::add_user(env.clone(), user.clone()); + // Crear usuarios virtuales para el admin y el usuario + let admin = Address::generate(&env); + let user = Address::generate(&env); - // Verify that the user appears in the list of authorized users - let users = TitleContract::get_users(env.clone()); - assert_eq!(users.contains(&user), true); + // Autenticar y setear al admin + client.mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "set_admin", + args: (&admin,).into_val(&env), + sub_invokes: &[], + }, + }]) + .set_admin(&admin); + + // Autenticar y agregar al usuario + client.mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "add_user", + args: (&user,).into_val(&env), + sub_invokes: &[], + }, + }]) + .add_user(&user); + + // Verificar que el usuario aparece en la lista de usuarios autorizados + let users = client.get_users(); + assert!(users.contains(&user)); } #[test] fn test_modify_title() { let env = Env::default(); - let admin = TestAddress::random(&env); - let user = TestAddress::random(&env); + let contract_id = env.register_contract(None, TitleContract); + let client = TitleContractClient::new(&env, &contract_id); + + // Crear usuarios virtuales para el admin y el usuario + let admin = Address::generate(&env); + let user = Address::generate(&env); let new_title = String::from_str(&env, "PrincesitoDan"); - TitleContract::set_admin(env.clone(), admin.clone()).unwrap(); - TitleContract::add_user(env.clone(), user.clone()); + // Autenticar y setear al admin + client.mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "set_admin", + args: (&admin,).into_val(&env), + sub_invokes: &[], + }, + }]) + .set_admin(&admin); - // Attempt to modify the title by the authorized user - assert!(TitleContract::modify_title(env.clone(), user.clone(), new_title.clone()).is_ok()); + // Autenticar y agregar al usuario + client.mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "add_user", + args: (&user,).into_val(&env), + sub_invokes: &[], + }, + }]) + .add_user(&user); - // Verify that the title was modified - assert_eq!(TitleContract::get_title(env.clone()), new_title); + // Crear un Vec a partir de un array + let args: Vec = Vec::from_array(&env, [ + user.into_val(&env), + new_title.clone().into_val(&env) + ]); + + // Autenticar al usuario y modificar el título + let result = client + .mock_auths(&[MockAuth { + address: &user, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "modify_title", + args: args.into_val(&env), // Usar el vector como argumento + sub_invokes: &[], + }, + }]) + .modify_title(&user, &new_title); + + // Verificar que el título fue modificado + assert_eq!(client.get_title(), new_title); } #[test] fn test_modify_admin() { let env = Env::default(); - let admin = TestAddress::random(&env); - let new_admin = TestAddress::random(&env); + let contract_id = env.register_contract(None, TitleContract); + let client = TitleContractClient::new(&env, &contract_id); + + // Crear usuarios virtuales para el admin y el nuevo admin + let admin = Address::generate(&env); + let new_admin = Address::generate(&env); - TitleContract::set_admin(env.clone(), admin.clone()).unwrap(); - TitleContract::modify_admin(env.clone(), new_admin.clone()).unwrap(); + // Autenticar y setear al admin + client.mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "set_admin", + args: (&admin,).into_val(&env), + sub_invokes: &[], + }, + }]) + .set_admin(&admin); - // Verify that only the new admin has the necessary permissions - assert_eq!(TitleContract::address_admin(env.clone()).unwrap(), new_admin); + // Autenticar al admin actual y modificar al nuevo admin + client.mock_auths(&[MockAuth { + address: &admin, + invoke: &MockAuthInvoke { + contract: &contract_id, + fn_name: "modify_admin", + args: (&new_admin,).into_val(&env), + sub_invokes: &[], + }, + }]) + .modify_admin(&new_admin); + + // Verificar que solo el nuevo admin tiene los permisos necesarios + assert_eq!(client.address_admin(), new_admin); } + diff --git a/soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user.1.json b/soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user.1.json new file mode 100644 index 0000000..4f00298 --- /dev/null +++ b/soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user.1.json @@ -0,0 +1,427 @@ +{ + "generators": { + "address": 3, + "nonce": 2 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "add_user", + "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": { + "symbol": "ADMIN" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "AUTH_USER" + }, + "val": { + "map": [ + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + "val": { + "bool": true + } + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "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": "set_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "set_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "add_user" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "__check_auth" + } + ], + "data": { + "vec": [ + { + "bytes": "55ddab4662f8c7341967cd20705c81cc0a672a66f2f4075305b792c6544f4cba" + }, + "void", + { + "vec": [ + { + "vec": [ + { + "symbol": "Contract" + }, + { + "map": [ + { + "key": { + "symbol": "args" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + { + "key": { + "symbol": "contract" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fn_name" + }, + "val": { + "symbol": "add_user" + } + } + ] + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "__check_auth" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "add_user" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "get_users" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "get_users" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user_and_get_users.1.json b/soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user_and_get_users.1.json new file mode 100644 index 0000000..4f00298 --- /dev/null +++ b/soroban-react-dapp/contracts/title/test_snapshots/test/test_add_user_and_get_users.1.json @@ -0,0 +1,427 @@ +{ + "generators": { + "address": 3, + "nonce": 2 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "add_user", + "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": { + "symbol": "ADMIN" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "AUTH_USER" + }, + "val": { + "map": [ + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + "val": { + "bool": true + } + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "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": "set_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "set_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "add_user" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "__check_auth" + } + ], + "data": { + "vec": [ + { + "bytes": "55ddab4662f8c7341967cd20705c81cc0a672a66f2f4075305b792c6544f4cba" + }, + "void", + { + "vec": [ + { + "vec": [ + { + "symbol": "Contract" + }, + { + "map": [ + { + "key": { + "symbol": "args" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + { + "key": { + "symbol": "contract" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fn_name" + }, + "val": { + "symbol": "add_user" + } + } + ] + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "__check_auth" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "add_user" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "get_users" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "get_users" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/soroban-react-dapp/contracts/title/test_snapshots/test/test_auth_control.1.json b/soroban-react-dapp/contracts/title/test_snapshots/test/test_auth_control.1.json new file mode 100644 index 0000000..fd86afb --- /dev/null +++ b/soroban-react-dapp/contracts/title/test_snapshots/test/test_auth_control.1.json @@ -0,0 +1,124 @@ +{ + "generators": { + "address": 3, + "nonce": 0 + }, + "auth": [], + "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": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "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": "error" + }, + { + "error": { + "context": "internal_error" + } + } + ], + "data": { + "string": "no contract running" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "error" + }, + { + "error": { + "context": "internal_error" + } + } + ], + "data": { + "string": "escalating error to panic" + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_admin.1.json b/soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_admin.1.json new file mode 100644 index 0000000..3f7f864 --- /dev/null +++ b/soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_admin.1.json @@ -0,0 +1,406 @@ +{ + "generators": { + "address": 3, + "nonce": 2 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "modify_admin", + "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": { + "symbol": "ADMIN" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "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": "set_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "set_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "modify_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "__check_auth" + } + ], + "data": { + "vec": [ + { + "bytes": "95046fe45bf3a081e1421969f52d18d52ddbff6ea7074c8dc097b7c44fb3b720" + }, + "void", + { + "vec": [ + { + "vec": [ + { + "symbol": "Contract" + }, + { + "map": [ + { + "key": { + "symbol": "args" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + { + "key": { + "symbol": "contract" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fn_name" + }, + "val": { + "symbol": "modify_admin" + } + } + ] + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "__check_auth" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "modify_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "address_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "address_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_title.1.json b/soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_title.1.json new file mode 100644 index 0000000..d40752b --- /dev/null +++ b/soroban-react-dapp/contracts/title/test_snapshots/test/test_modify_title.1.json @@ -0,0 +1,670 @@ +{ + "generators": { + "address": 3, + "nonce": 3 + }, + "auth": [ + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "add_user", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "modify_title", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "PrincesitoDan" + } + ] + } + }, + "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": { + "symbol": "ADMIN" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "AUTH_USER" + }, + "val": { + "map": [ + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + "val": { + "bool": true + } + } + ] + } + }, + { + "key": { + "symbol": "TITLE" + }, + "val": { + "string": "PrincesitoDan" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 2 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 3 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": 3 + } + }, + "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": "set_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "set_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "add_user" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "symbol": "__check_auth" + } + ], + "data": { + "vec": [ + { + "bytes": "55ddab4662f8c7341967cd20705c81cc0a672a66f2f4075305b792c6544f4cba" + }, + "void", + { + "vec": [ + { + "vec": [ + { + "symbol": "Contract" + }, + { + "map": [ + { + "key": { + "symbol": "args" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + { + "key": { + "symbol": "contract" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fn_name" + }, + "val": { + "symbol": "add_user" + } + } + ] + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000002", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "__check_auth" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "add_user" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "modify_title" + } + ], + "data": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "PrincesitoDan" + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "symbol": "__check_auth" + } + ], + "data": { + "vec": [ + { + "bytes": "ddbc5cd1e35ce98941b7026460d7c6e0365697824e6158b949bc6964d715a7fb" + }, + "void", + { + "vec": [ + { + "vec": [ + { + "symbol": "Contract" + }, + { + "map": [ + { + "key": { + "symbol": "args" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + }, + { + "string": "PrincesitoDan" + } + ] + } + }, + { + "key": { + "symbol": "contract" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "fn_name" + }, + "val": { + "symbol": "modify_title" + } + } + ] + } + ] + } + ] + } + ] + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000003", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "__check_auth" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "modify_title" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "get_title" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "get_title" + } + ], + "data": { + "string": "PrincesitoDan" + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file diff --git a/soroban-react-dapp/contracts/title/test_snapshots/test/test_set_admin.1.json b/soroban-react-dapp/contracts/title/test_snapshots/test/test_set_admin.1.json new file mode 100644 index 0000000..3dfb6e8 --- /dev/null +++ b/soroban-react-dapp/contracts/title/test_snapshots/test/test_set_admin.1.json @@ -0,0 +1,212 @@ +{ + "generators": { + "address": 2, + "nonce": 1 + }, + "auth": [ + [], + [] + ], + "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": { + "symbol": "ADMIN" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "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": "set_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "set_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": null, + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_call" + }, + { + "bytes": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "symbol": "address_admin" + } + ], + "data": "void" + } + } + }, + "failed_call": false + }, + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "diagnostic", + "body": { + "v0": { + "topics": [ + { + "symbol": "fn_return" + }, + { + "symbol": "address_admin" + } + ], + "data": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + } + } + }, + "failed_call": false + } + ] +} \ No newline at end of file From a491ae2f1bbc5aac750ab6e6281ea8efcc3a47c6 Mon Sep 17 00:00:00 2001 From: "daniel.andrade1991@gmail.com" Date: Tue, 3 Sep 2024 00:32:05 -0400 Subject: [PATCH 4/5] feat: Update README with deployment and admin setup instructions, improve ManageTitle component - Updated README.md with comprehensive instructions on setting up the application, deploying the smart contract, and configuring the admin user. - Deployed the smart contract to the Stellar blockchain using Soroban. - Enhanced ManageTitle.tsx component: - Implemented automatic refresh for the list of authorized users. - Added automatic form field clearing after actions like adding a user, modifying the admin, or changing the title. - Improved semantic HTML structure: set contract section titles with larger, bold font. --- .../.soroban/identity/admin.toml | 2 +- .../.soroban/network/testnet.toml | 2 + soroban-react-dapp/README.md | 127 ++++++++++++++---- soroban-react-dapp/contracts/deployments.json | 2 +- .../src/components/home/HomePageTitle.tsx | 6 +- .../src/components/web3/ManageTitle.tsx | 44 +++--- 6 files changed, 136 insertions(+), 47 deletions(-) create mode 100644 soroban-react-dapp/.soroban/network/testnet.toml diff --git a/soroban-react-dapp/.soroban/identity/admin.toml b/soroban-react-dapp/.soroban/identity/admin.toml index 2872b71..8b13789 100644 --- a/soroban-react-dapp/.soroban/identity/admin.toml +++ b/soroban-react-dapp/.soroban/identity/admin.toml @@ -1 +1 @@ -secret_key = "SDDWPQWJFO7UGGFUBOZ4HZJDPBA62MWY3NUK7QTRL2LOTUVT5J3CRY7H" + diff --git a/soroban-react-dapp/.soroban/network/testnet.toml b/soroban-react-dapp/.soroban/network/testnet.toml new file mode 100644 index 0000000..6b6844f --- /dev/null +++ b/soroban-react-dapp/.soroban/network/testnet.toml @@ -0,0 +1,2 @@ +rpc_url = "https://soroban-testnet.stellar.org/" +network_passphrase = "Test SDF Network ; September 2015" diff --git a/soroban-react-dapp/README.md b/soroban-react-dapp/README.md index 6039400..2e03a65 100644 --- a/soroban-react-dapp/README.md +++ b/soroban-react-dapp/README.md @@ -1,57 +1,134 @@ 🛡️ Welcome to Title Contract Hello and welcome to Title Contract! 🎉 - 🚀 What is Title? -Title is a special wallet containing the following crucial data: +This contract acts as the guardian, controlling who can modify the character associated with this wallet. Only those with the "magic trick" will have the power to make changes. +🛠️ Project Setup + +1. Clone the Repository: - Account Admin: - Public Key: GAMPJTSVJSEVX4KKWVY2G7JM66AI6PPQIZMTW2EI6ZVJLEZLMKI7GAFK - Secret Key: SCHWRT7BOMNJPOZECVKWZND2XFMEGVVJ4ILZEPFQIRTCYVPGCGKKFAIA +Follow the instructions here: Manual Cloning: -This contract is the guardian that decides who can change the character associated with the wallet. Only those who know "the magic trick" will have that power. -🛠️ Project Setup -1. Environment Configuration readme soroban-react-dapp +https://create-soroban-dapp.paltalabs.io/create-soroban-dapp/manual_cloning.html -First, ensure that Soroban is set up in your environment. If you haven’t done so yet, you can add the admin identity by running: +Navigate to the Project Directory: bash -soroban config identity add --secret-key admin +cd soroban-react-dapp -And, of course, you’ll need to input the secret key for Title (listed above). -2. Build and Testnet +2. Set Up Your Secrets: -Next, build and deploy the contract on the testnet. Simply run: +When deploying contracts, you’ll need the secret key of the deployer account. Store this key in a file located at ./contracts/.env. + +To set up your secrets, run: bash -yarn deploy testnet title +cp contracts/.env.example contracts/.env -yarn testtitle testnet +If you’re already in the contracts folder (e.g., inside the Docker container), run: + +bash + +cp .env.example .env + +Edit the .env file to include your secret keys and RPC URLs. The file should look like this: + +plaintext + +# Stellar accounts Secret Keys +ADMIN_SECRET_KEY= + +# RPC Setup +MAINNET_RPC_URL=https://mainnet.stellar.validationcloud.io/v1/3uELU0BKP-ARJhn6hngelkg5Y24i8xGgUA9QtB8KsYc -This should execute like so: +USER_1= +USER_2= +USER_3= +NEW_ADMIN= + +You can generate new accounts and private keys from Stellar Laboratory. Copy your secret keys into the .env file. + +Note: The initial ADMIN will start as the administrator. After executing test_title.txs, the contract’s admin will be NEW_ADMIN, and USER_1 and USER_2 will be authorized to modify the title. Create multiple accounts in Stellar Laboratory or use your own for testing the smart contract. + +If you plan to deploy on the mainnet, you'll need a Mainnet RPC Provider. Consider using providers like Validation Cloud or NowNodes. + +3. Container Setup: + +Navigate to the right directory: + +bash + +cd soroban-react-dapp/ + +Bring up the necessary containers: bash -root@3b15f88a2fa0:/workspace/contracts# yarn testtitle testnet +docker-compose up -d +./run.sh -3. Launch the Application +4. Build and Test Contracts: -Now that the contract is set up, it’s time to see the magic in action. Start the application with: +Run the following commands: bash -yarn dev +cd contracts +make build +make test +yarn deploy + +You can test the contract by invoking it with the ID shown in the console: + +bash + +soroban contract invoke --id XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX --source admin --network testnet + +For testnet: + +bash + +soroban config network add --rpc-url https://soroban-testnet.stellar.org/ --network-passphrase "Test SDF Network ; September 2015" testnet + +5. Execute the Test Title: + +Run: + +bash + +yarn testtitle testnet + +Run the Frontend: -Watch what happens and get ready to explore! -4. Freight Configuration +6. Navigate back and start the development server: + +bash + + cd .. + yarn dev + + Watch what happens and get ready to explore! + +7. Freight Configuration: + + Don’t forget to configure Freight with Title to efficiently manage your tests. + +8. Additional Testing: + + Finally, add more test addresses to ensure that only those chosen by Title can modify the character. Test the security of your contract and enjoy the process! + +Extra: Stopping the Containers: + +When you’re finished, you can stop the containers by running: + +bash -Don’t forget to configure Freight with Title to efficiently manage your tests. -5. Additional Testing +docker-compose down -Finally, add more test addresses to ensure that only those chosen by Title can change the character. Test the security of your contract and have fun in the process! +################################################################################### # Welcome to your soroban react dapp boilerplate! diff --git a/soroban-react-dapp/contracts/deployments.json b/soroban-react-dapp/contracts/deployments.json index 5d131fc..78dd0e0 100644 --- a/soroban-react-dapp/contracts/deployments.json +++ b/soroban-react-dapp/contracts/deployments.json @@ -12,6 +12,6 @@ { "contractId": "title", "networkPassphrase": "Test SDF Network ; September 2015", - "contractAddress": "CAS3V3WZFZYQMHFXRJJOCYT2JMLO6CFZSIQK64NN4WR3WN4OB5TXV3XL" + "contractAddress": "CACLC6ZO3XLNJF2X6KDLFHHNSOYINOETOV7ABKVN2EQPWKGAYB7IYPPR" } ] \ No newline at end of file diff --git a/soroban-react-dapp/src/components/home/HomePageTitle.tsx b/soroban-react-dapp/src/components/home/HomePageTitle.tsx index 0b0da39..f5b2fca 100644 --- a/soroban-react-dapp/src/components/home/HomePageTitle.tsx +++ b/soroban-react-dapp/src/components/home/HomePageTitle.tsx @@ -8,7 +8,7 @@ const StyledIconLink = styled(Link)(() => [ ]) export const HomePageTitle: FC = () => { - const title = 'Soroban React Dapp' + const title = 'Soroban React Dapp - Title' const desc = 'Full-Stack DApp Boilerplate for Soroban smart contracts' const githubHref = 'https://github.com/paltalabs/create-soroban-dapp/' @@ -41,11 +41,11 @@ export const HomePageTitle: FC = () => {

Adapted by {' '} - Benjamin Salon + Princeso Dan {' '} in collaboration with {' '} { const contract = useRegisteredContract("title"); + // 1. Implementación del estado reactivo para la lista de usuarios autorizados const fetchTitle = useCallback(async () => { if (!server || !contract) return; @@ -71,10 +72,13 @@ export const ManageTitle: FC = () => { } }, [server, contract]); + // Intervalo para actualización automática de usuarios autorizados useEffect(() => { fetchTitle(); fetchAdminAddress(); - fetchAuthorizedUsers(); + const intervalId = setInterval(fetchAuthorizedUsers, 1000); // Actualización cada 1 segundo + + return () => clearInterval(intervalId); // Limpieza del intervalo }, [fetchTitle, fetchAdminAddress, fetchAuthorizedUsers]); const modifyTitle = async () => { @@ -95,7 +99,9 @@ export const ManageTitle: FC = () => { }); toast.success("Title modified."); setCurrentTitle(newTitle); - setNewTitle(''); // Limpiar campo de entrada + + // Limpieza del campo de entrada + setNewTitle(''); } catch (error) { console.error("Error modifying title:", error); toast.error('User not authorized.'); @@ -121,7 +127,9 @@ export const ManageTitle: FC = () => { sorobanContext }); toast.success("User added."); - setNewUser(''); // Limpiar campo de entrada + + // Limpieza del campo de entrada + setNewUser(''); } catch (error) { console.error("Error adding user:", error); toast.error('You are not the admin, you are not authorized for this.'); @@ -148,7 +156,9 @@ export const ManageTitle: FC = () => { }); toast.success("Admin modified."); setAdminAddress(newAdmin); - setNewAdmin(''); // Limpiar campo de entrada + + // Limpieza del campo de entrada + setNewAdmin(''); } catch (error) { console.error("Error modifying admin:", error); toast.error('You are not authorized for this.'); @@ -159,29 +169,30 @@ export const ManageTitle: FC = () => { return ( + {/* Aplicación de estilos para los títulos */} - Current Title - {currentTitle || "No Title Set"} + Current Title + {currentTitle || "No Title Set"} - Authorized Users + Authorized Users {authorizedUsers.length > 0 ? ( - authorizedUsers.map((user, idx) => {user}) + authorizedUsers.map((user, idx) => {user}) ) : ( - No Authorized Users + No Authorized Users )} - Admin Address - {adminAddress || "No Admin Set"} + Admin Address + {adminAddress || "No Admin Set"} - New Title + New Title setNewTitle(e.target.value)} />