aelf 백서

bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 41쪽 중 23쪽

f-deploy -a $WALLET_ADDRESS -p $WALLET_PASSWORD -c $CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ Command Prompt $CONTRACT_PATH = Get-ChildItem -Recurse -Filter "*patched*" | Select-Object -First 1 -ExpandProperty FullName $env :CONTRACT_PATH = $CONTRACT_PATH Command Prompt aelf-deploy -a $env :WALLET_ADDRESS -p $env :WALLET_PASSWORD -c $env :CONTRACT_PATH -e https://tdvw-test-node.aelf.io/ Please wait for approximately 1 to 2 minutes. If the deployment is successful, it will provide you with the contract address. Copy the smart contract address from the address field Export your smart contract address: Linux and macOs Windows Terminal export CONTRACT_ADDRESS = "YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" Command Prompt $env :CONTRACT_ADDRESS = "YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS" tip ℹ️ Note: You are to copy the smart contract address as we will be referencing it in the next steps! info 🎉 You have successfully deployed your Expense Tracker dApp smart contract on the aelf testnet! In the next steps, we will be building the frontend components that allow us to interact with our deployed smart contract! Step 4 - Interact with Your Deployed Smart Contract through dApp ​ Project Setup ​ Let's start by cloning the frontend project repository from github. Terminal git clone https://github.com/AElfProject/aelf-samples.git Next, navigate to the frontend project directory with this command: Terminal cd aelf-samples/expense-tracker/2-dapp Once you're inside the 2-dapp directory, open the project with your preferred IDE (e.g., VSCode). You should see the project structure as shown below. Install necessary libraries ​ Run this command in the terminal to install all necessary packages and libraries: Terminal npm install We are now ready to build the frontend components of our Expense-Tracker dApp. Configure Portkey Provider & Write Connect Wallet Function ​ Now, we'll set up our Portkey wallet provider to allow users to connect their Portkey wallets to the dApp and interact with the smart contract. We'll be interacting with the already deployed Expense Tracker smart contract for this tutorial. Step 1. Locate the File: Go to the src/hooks/useExpenseTrackerSmartContract.ts file. Step 2. Fetch the Smart Contract: Find the comment //Step A - Function to fetch a smart contract based on deployed wallet address Replace the existing fetchContract function with this updated code: useExpenseTrackerSmartContract.ts //Step A - Function to fetch a smart contract based on deployed wallet address const fetchContract = async ( ) => { if ( ! provider ) return null ; try { // 1. get the aelf dAppChain using provider.getChain const chain = await provider ?. getChain ( "tDVW" ) ; if ( ! chain ) throw new Error ( "No chain" ) ; //Address of Expense Tracker Smart Contract //Replace with Address of Deployed Smart Contract const address = "your_deployed_expense_tracker_contract_address" ; // 2. get the Expense Tracker contract const contract = chain ?. getContract ( address ) ; setSmartContract ( contract ) ; } catch ( error ) { console . log ( error , "====error" ) ; } } ; tip ℹ️ Note: You are to replace the address placeholder with your deployed Expense Tracker smart contract address from "Deploy Smart Contract" step! example: Replace with Address of Deployed Smart Contract const address = "your_deployed_expense_tracker_contract_address"; Explanation: fetchContract Function : This function fetches a smart contract based on the given chain symbol (e.g., "AELF" or "tDVW") and the contract address. Check Provider : If no provider is available, the function returns null. Fetch Chain : The function fetches chain information using the provider. Get Contract : It retrieves the smart contract instance from the chain. AELF represents the mainnet chain and tDVW represents the testnet chain respectively on the aelf blockchain. Step 3. Initialize and Fetch the Smart Contracts: Find the comment // Step B - Effect hook to initialize and fetch the smart contract when the provider changes. Replace the existing useEffect hook with this updated code: useSmartContract.ts // Step B - Effect hook to initialize and fetch the smart contract when the provider changes useEffect ( ( ) => { fetchContract ( ) ; } , [ provider ] ) ; // Dependency array ensures this runs when the provider changes Explanation: useEffect Hook : This hook initializes and fetches the smart contracts when the provider changes. Check Provider : If no provider is available, the function returns null. Fetch Contracts : It fetches and sets the smart contracts. By following these steps, we'll configure the Portkey provider to connect users' wallets to our app and interact with the Expense Tracker smart contract which includes the tracking and management of expenses functionalities. This setup will enable our frontend components to perform actions like addNewExpense , updateExpense , deleteExpense and getExpenseData etc. Configure Connect Wallet Function ​ Step 1: Locate the File Go to the src/components/layout/header/index.tsx file. Step 2: Write the Connect Wallet Function The header/index.tsx file is the header of our Expense Tracker dApp. It allows users to connect their Portkey wallet with the Expense Tracker dApp. Before users can interact with the smart contract, we need to write the Connect Wallet function. Find the comment // Step C - Connect Portkey Wallet . Replace the existing connect function with this code snippet: header/index.tsx const connect = async ( walletProvider ? : IPortkeyProvider ) => { // Step C - Connect Portkey Wallet const accounts = await ( walletProvider ? walletProvider : provider ) ?. request ( { method : MethodsBase . REQUEST_ACCOUNTS , } ) ; const account = accounts ?. AELF && accounts ?. AELF [ 0 ] ; if ( account ) { setCurrentWalletAddress ( account . replace ( / ^ ELF_ / , "" ) . replace ( / _AELF $ / , "" ) ) ; setIsConnected ( true ) ; } ! walletProvider && toast . success ( "Successfully connected" ) ; } ; Explanation: connect Function : This function connects the user's Portkey wallet with the dApp. Fetch Accounts : It fetches the wallet accounts using the provider. Log Accounts : Logs the accounts to the console for debugging. Set Wallet Address : Sets the current wallet address state variable with the fetched account. In this code, we fetch the Portkey wallet account using the provider and update the wallet address state variable. An alert notifies the user that their wallet is successfully connected. With the connect wallet function defined, we're ready to write the remaining functions in the next steps. Configure Create Expense Form ​ Step 1: Locate the File Go to the src/pages/home/index.tsx file. This file contains all the functionalities like show user's Expense, AddExpense, UpdateExpense, DeleteExpense, etc. Step 2: Prepare Form to Add and Update Expenses Find the comment // Step D - Configure Expense Form . Replace the form variable with this code snippet: home/index.tsx // Step D - Configure Expense Form const form = useForm < z . infer < typeof formSchema >> ( { resolver : zodResolver ( formSchema ) , defaultValues : { description : "" , amount : "" , } , } ) ; Here's what the function does: ​ Initializes a new form variable with default values needed to add a new expense. Fields include: description and amount . Now the form is ready for users to fill in the necessary details. Check Contract Initialization ​ Step 1: Locate the File Go to the src/pages/home/index.tsx file. This file contains all the functionalities like checkIsContractInitialized , initializeContract , addNewExpense , updateExpense , deleteExpense and getExpenseData . Step 2: Prepare a Function to Check Whether the Contract is Initialized or not Scroll down to find the comment // step 1 - Check If Contract is Initialized or not . Replace the existing checkIsContractInitialized function with this code snippet: home/index.tsx // step 1 - Check If Contract is Initialized or not const checkIsContractInitialized = async ( ) => { const result = await smartContract ?. callViewMethod ( "GetInitialStatus" , "" ) ; // Call the GetInitialStatus method which is present on Smart Contract setIsContractInitialized ( result ?. data ?. value ) ; // Expect value True if it's Initialized otherwise NULL if it's not } ; Initialize Contract ​ Scroll down to find the comment // step 2 - Initialize the smart contract . Replace the existing checkIsContractInitialized function with this code snippet: home/index.tsx // step 2 - Initialize the smart contract const initializeContract = async ( ) => { let initializeLoadingId ; try { // Start Loading initializeLoadingId = toast . loading ( "Initializing a Contract.." ) ; await smartContract ?. callSendMethod ( "Initialize" , // Function Name currentWalletAddress as string , // User Wallet Address { } // No Arguments ) ; // Update Loading Message with Success toast . update ( initializeLoadingId , { render : "Contract Successfully Initialized" , type : "success" , isLoading : false , } ) ; return ; } catch ( error : any ) { // Update Loading Message with Error toast . update ( initializeLoadingId as Id , { render : error . message , type : "error" , isLoading : false , } ) ; return ; } finally { // Remove Loading Message removeNotification ( initializeLoadingId as Id ) ; } } ; Add New Expense ​ Write the function to add a new expense. Find the comment // step 3 - Add a New Expense using Smart Contract . Replace the existing addNewExpense function with this code snippet: home/index.tsx // step 3 - Add a New Expense using Smart Contract const addNewExpense = async ( values : { description : string ; amount : string ; } ) => { let addLoadingId ; try { // Start Loading addLoadingId = toast . loading ( "Adding a New Expense.." ) ; setFormLoading ( true ) ; // Prepare Arguments for Create a New Expense const sendData = { description : values . description , amount : values . amount , category : selectedCategory ?. value , currency : "USD" , } ; // Call AddExpense Function of Smart Contract await smartContract ?. callSendMethod ( "AddExpense" , currentWalletAddress as string , sendData ) ; // Update Loading Message with Success toast . update ( addLoadingId , { render : "New Expense Successfully Adding" , type : "success" , isLoading : false , } ) ; // Get New Data from Contract getExpenseData ( ) ; } catch ( error : any ) { // Update Loading Message with Error toast . update ( addLoadingId as Id , { render : error . message , type : "error" , isLoading : false , } ) ; } finally { // Close Form Modal handleCloseModal ( ) ; // Remove Loading Message removeNotification ( addLoadingId as Id ) ; setFormLoading ( false ) ; } } ; What This Function Does: ​ Calls Smart Contract Method : It interacts with the aelf blockchain's smart contract to add a new Expense using AddExpense Function. Next, we'll write the Update Expense function. Update Expense ​ Write the function to update a selected expense. Scroll down to find the comment // step 4 - Update the Expense . Replace the existing updateExpense function with this code snippet: home/index.tsx // step 4 - Update the Expense const updateExpense = async ( values : { description : string ; amount : string ; } ) => { let updateLoadingId ; try { // Start Loading updateLoadingId = toast . loading ( "Updating a Expense.." ) ; setFormLoading ( true ) ; // Prepare Arguments for Update the Expense const sendData = { expenseId : updateId , description : values . description , amount : values . amount , category : selectedCategory ?. value , currency : "USD" , } ; // Call UpdateExpense Function of Smart Contract await smartContract ?. callSendMethod ( "UpdateExpense" , currentWalletAddress as string , sendData ) ; // Update Loading Message with Success toast . update ( updateLoadingId , { render : "Expense Successfully Updated" , type : "success" , isLoading : false , } ) ; // Get New Data from Contract getExpenseData ( ) ; } catch ( error : any ) { // Update Loading Message with Error toast . update ( updateLoadingId as Id , { render : error . message , type : "error" , isLoading : false , } ) ; } finally { // Close Form Modal handleCloseModal ( ) ; // Remove Loading Message removeNotification ( updateLoadingId as Id ) ; setFormLoading ( false ) ; } } ; What This Function Does: ​ Calls Smart Contract Method : It interacts with the blockchain smart contract to Update the existing expense using UpdateExpense function. Get New Data from Contract : It calls the getExpenseData function to get updated data from the smart contract. Next, we'll write the Delete Expense function. Delete Expense ​ Write the Function to delete an existing expense. Scroll down to find the comment // step 5 - Delete the Expense . Replace the existing deleteExpense function with the following code snippet: home/index.tsx // step 5 - Delete the Expense const deleteExpense = async ( data : IExpenseObject ) => { let deleteLoadingId ; try { // Start Loading deleteLoadingId = toast . loading ( "Removing a Expense.." ) ; setDeletingId ( data . expenseId ) ; // set Deleting Id for Loading on Button // Call DeleteExpense Function of Smart Contract for Delete the Expense await smartContract ?. callSendMethod ( "DeleteExpense" , currentWalletAddress as string , { value : data . expenseId } ) ; // Update Loading Message with Success toast . update ( deleteLoadingId , { render : "Expense Successfully Removed" , type : "success" , isLoading : false , } ) ; // Get New Data from Contract await getExpenseData ( ) ; } catch ( error : any ) { // Update Loading Message with Error toast . update ( deleteLoadingId as Id , { render : error . message , type : "error" , isLoading : false , } ) ; } finally { setDeletingId ( null ) ; // Remove Loading Message removeNotification ( deleteLoadingId as Id ) ; } } ; What This Function Does: ​ Calls Smart Contract Method : It interacts with the blockchain smart contract to delete an existing expense using the DeleteExpense function. Get New Data from Contract : It calls the getExpenseData function to get updated data from the smart contract. Next, we'll write the Handle Submit Form function. Handle Submit Form ​ Write a function to make the move. Scroll down to find the comment // step 6 - Handle Submit Form . Replace the existing onSubmit function with this code snippet: home/index.tsx // step 6 - Handle Submit Form const onSubmit = async ( values : { description : string , amount : string } ) => { // Check Whether Contract Initialized or not if ( isContractInitialized !== true ) { await initializeContract ( ) ; // initialize the contract if it's not initialized before } // Check Whether Form is for Create or Update the Expense if ( ! ! updateId ) { await updateExpense ( values ) ; // Call updateExpense for Update the Expense } else { await addNewExpense ( values ) ; // Call updateExpense for Create a new Expense } } ; What This Function Does: ​ Check initialized contract : It checks whether the smart contract is initialized or not by using initializeContract function. Update Expense : Call the updateExpense function if updatedId has any value. Add Expense : Call the addNewExpense function if updatedId does not have any value. Here, we have completed functions to Add Expense , Update Expense and Delete Expense and now it's time to write a function to Fetch Expense from the smart contract. Fetch All Expenses ​ Scroll up to find the comment // step 7 - Fetch All Expenses . Replace the existing getExpenseData function with this code snippet: home/index.tsx // step 7 - Fetch All Expenses const getExpenseData = async ( ) => { try { const result = await smartContract ?. callViewMethod ( "ListExpenses" , { value : currentWalletAddress , } ) ; console . log ( "result" , result ?. data ) ; setExpenseData ( result ?. data ? result ?. data . expenses : [ ] ) ; } catch ( error ) { console . log ( "error======" , error ) ; } finally { setLoading ( false ) ; } } ; Here's what the function does: ​ Fetches Expense Data: It calls ListExpenses to get the list of all expenses from the Expense Tracker smart contract. Set Expense on State: Get the result data from the smart contract and set an array of all expenses into expenseData State. We have prepared necessary function to fetch all the expenses created from a connected user's wallet. Now that we've written all the necessary frontend functions and components, we're ready to run the Expense Tracker dApp application in the next step. Run Application ​ In this step, we will run the Expense Tracker dApp application. To begin, run the following command on your terminal. Terminal npm run dev info Note : Ensure that you are running this command under the expense-tracker/2-dapp folder. You should observe the following as shown below. Upon clicking on the localhost URL , you should be directed to the Expense Tracker dApp landing page as shown below. tip If you are developing and testing this with github codespace, you can use port forward to test the web server that is running in codespace, here is the link on how to use port forward for codespace https://docs.github.com/en/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace Usually codespaces automatically forward ports, you should see a pop-up message at the bottom right of your codespace browser window as shown in the diagram below: Click the link to open the Expense Tracker dApp in the browser. Create Portkey Wallet ​ info Portkey is the first AA wallet from aelf's ecosystem, migrating users, developers and projects from Web2 to Web3 with DID solution. Users can swiftly log into Portkey via their Web2 social info with no private keys or mnemonics required. Underpinned by social recovery and decentralized guardian design, Portkey safeguards users' assets from centralized control and theft. Portkey has a unique payment delegation mechanism which enables interested parties to function as delegatees to pay for user activities on users' behalf. This means that users can create accounts for free and fees for other usages may also be covered in Portkey. Portkey also provides crypto on/off-ramp services, allowing users to exchange fiat with crypto freely. It supports the storage and management of various digital assets such as tokens, NFTs, etc. The compatibility with multi-chains and seamless connection to all kinds of DApps makes Portkey a great way to enter the world of Web3. With DID solution as its core, Portkey provides both Portkey Wallet and Portkey SDKs. For more information, you may visit the official documentation for Portkey at https://doc.portkey.finance/ . Download the Chrome extension for Portkey from https://chromewebstore.google.com/detail/portkey-wallet/iglbgmakmggfkoidiagnhknlndljlolb . info The Portkey extension supports Chrome browser only (for now). Please ensure that you are using Chrome browser. You may download Chrome from https://www.google.com/intl/en_sg/chrome/ . Once you have downloaded the extension, you should see the following on your browser as shown below. Click on Get Start and you should see the following interface as shown below. Sign up Switch to ael
프로젝트로 돌아가기