aelf 백서

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

ate Token Button. You will get a transaction request on your Portkey wallet. Proceed to Sign the transaction. After transaction is succesfully signed, you will get a successful/failed transaction notification. Now, the transaction will be validated on the aelf blockchain. Let's wait till the transaction gets validated. Once the transaction is successfully validated, a new Sign transaction request will pop-up on Portkey to Create Token on the dAppChain . Click on the Approve button and wait for the transaction to complete. After the successful creation of the token on the dAppChain, a new Sign transaction request will pop-up on Portkey to Issue Tokens On the dAppChain . Click on the Approve button and wait for the transaction to complete. Once tokens are issued successfully on the dAppChain, a new Sign transaction request will pop-up on Portkey to Transfer Tokens to the Staking Contract to distribute future staking rewards. Click on the Approve button and wait for the transaction to complete. Once the reward tokens are transferred successfully, a new Sign transaction request will pop-up on Portkey to Initialize the Staking Contract . Click on the Approve button and wait for the transaction to complete. Once the transaction is suceessfully completed, a notification will pop-up and the Token balance will be visible on the staking widget like below. Stake Tokens Enter the amount to stake the tokens and click on the Stake $TOKEN Button. A new Sign transaction request will pop-up on Portkey to Transfer $TOKEN amount to the staking contract . Click on the Sign Button. Now You will get another transaction request to Deposit $TOKEN on the staking contract on the Portkey Wallet. Click on the Sign Button. A notification will pop-up that the $TOKEN are Staked Succesfully . The Token balance will be updated. As we have completed all the necessary steps to stake the token, now it's time to withdraw the tokens. There are two ways to withdraw the staked amount. Emergency Withdraw Token : User can withdraw staked tokens at anytime before the staking (lock) time period ends. Withdraw Token : User can withdraw staked tokens once the lock time period is over. Let's do Emergency Withdraw Token in the next step. Emergency Withdraw Tokens After clicking on the staked token, A staked token entry will be visible on the Staked $TOKEN section like below. Click on Emergency Withdraw Button. Now, a transaction request will pop-up on the Portkey wallet. The staked amount will be returned without any rewards and the token balance will be updated. As we have completed Emergency Withdraw Tokens functioanlity. It's time to try Withdraw Token functionality. Withdraw Token First, the connected wallet needs to stake the tokens on the staking contract as we have already completed this during Stake Tokens step. You need to wait till the lock time period is over for the staked amount. After the lock period is over, you will be able to see your staked amount in Available to Withdraw $TOKEN section as shown below. Click on Withdraw button to withdraw the amount including staking Rewards . 1.1 times the amount of the staked tokens. Now, You will get the transaction request on the Portkey wallet to withdraw the staked amount. Click on the Sign button. Your staked tokens including rewards will be transferred to the connected wallet once the withdrawal request completes. success 🎉 Congratulations Learners! You have successfully built your Staking dApp! 🎯 Conclusion ​ 🎊 Congratulations on setting up your development environment and interacting with both the multi-token and staking smart contracts! 🎊 You've now built a solid foundation for handling advanced token operations and staking functionalities on the aelf blockchain. 🌟 📚 What You've Learned Throughout this section, you've gained vital skills in: 🛠️ Setting Up Your Development Environment : You installed essential tools like the .NET SDK, aelf contract templates, and the aelf deploy tool to prepare for smart contract development. 📦 Installing Node.js, Yarn, and aelf-command : These tools enable efficient interaction with the aelf blockchain, facilitating wallet creation and transaction management. 💡 Getting Token Seed : You obtained a TOKEN seed from the testnet faucet, a fundamental step in creating fungible tokens. 🔧 Configuring Frontend Integration : You set up a frontend that interacts with both the multi-token and staking contracts, enabling user-friendly functionality including functions like token creation, token issuance, stake tokens, and withdraw tokens in your dApp. 🔍 Final Output By now, you should have: 📜 Successfully set up your development environment and installed all required packages. 💻 Configured your frontend to interact with both the multi-token and staking smart contracts, enabling functionalities like creating tokens, issuing them on the dAppChain, staking, and withdrawing tokens. ➡️ What's Next? With a comprehensive understanding of token creation, staking, and contract interaction, you're prepared to explore further aspects of blockchain development. Consider diving into: 📊 Advanced Smart Contract Logic : Add more complex features and security to your contracts. Enhanced Staking Protocols : Learn about advanced staking mechanisms and rewards structures to elevate your dApp. 🌐 Cross-Chain Interoperability : Explore how aelf’s cross-chain capabilities enable seamless communication between different blockchains. Keep experimenting and innovating with aelf! Your journey into decentralized finance and blockchain development is just getting started. 🚀 Happy coding and building on the aelf blockchain! 😊 Step 1 - Setting up your development environment Step 2 - Develop Smart Contract Start Your Smart Contract Project Adding Your Smart Contract Code Building Smart Contract Step 3 - Deploy Smart Contract Step 4 - Getting TOKEN Seed Step 5 - Interact with Your Deployed Smart Contracts Project Setup Configure Portkey Provider & Write Contract Hooks Function Configure Connect Wallet Function Configure Create TOKEN Form Get CrossChain Contract Get the parent chain height Fetch the Merkle path Get Token Contract Create Fungible Token on the MainChain Create Fungible Token on dAppChain Issue the created token on the dAppChain Transfer Token to Staking Contract Initialize the staking contract Configure Submit Form Fetch Token Data Deposit Stake Amount on the Staking Contract Fetch Deposited (Staked) Tokens Fetch Total Staked Amount Withdraw Staked Tokens Emergency Withdraw Staked Tokens Set Staking Contract Address Run Application 🎯 Conclusion ## /quick-start/developers/dice-game-dapp On this page Description : This contract is moderately complex. It demonstrates the use of state variables, user interactions, and random number generation using Aetherlink VRF to create a dice game where users can bet on the outcome of the dice roll. Aetherlink is a decentralized oracle network on aelf blockchain. Purpose : To introduce you to more advanced concepts such as state management, event handling, and randomization using oracle networks in smart contracts. Difficulty Level : Moderate Step 1 - Setting up your development environment ​ Local Codespaces Basic knowledge of terminal commands IDE - Install VS Code Note for Apple Silicon users: Ensure that Rosetta is installed, if it is not, use the following command: Terminal softwareupdate --install-rosetta Install Required Packages Install dotnet 8.0.x SDK Install aelf contract templates Linux and macOs Windows Terminal dotnet new --install AElf.ContractTemplates Command Prompt dotnet new install AElf.ContractTemplates AELF.ContractTemplates contains various predefined templates for the ease of developing smart contracts on the aelf blockchain. Install aelf deploy tool Terminal dotnet tool install --global aelf.deploy aelf.deploy is a utility tool for deploying smart contracts on the aelf blockchain. Please remember to export PATH after installing aelf.deploy. info ℹ️ Note: If you have installed aelf.deploy and your terminal says that there is no such command available, please uninstall and install aelf.deploy. Install Node.js and Yarn Install Node.js Install Yarn Install aelf-command Linux and macOs Windows Terminal sudo npm i -g aelf-command Command Prompt npm i -g aelf-command aelf-command is a CLI tool for interacting with the aelf blockchain, enabling tasks like creating wallets and managing transactions. Provide required permissions while installing aelf-command globally. Visit aelf-devcontainer-template . Click the Use this template button. Choose Create a new repository . Enter a suitable repository name. Click Create repository . Within the GitHub interface of your new repository, click on Code . Select Codespaces . Click on the + sign to create a new Codespace. After some time, your workspace will load with the contents of the repository. You can now continue your development using GitHub Codespaces. Step 2 - Develop Smart Contract ​ Start Your Smart Contract Project ​ Open your Terminal . Enter the following command to generate a new project: Terminal mkdir dice-game cd dice-game dotnet new aelf -n DiceGame Adding Your Smart Contract Code ​ Now that we have a template dice game project, we can customise the template to incorporate our own contract logic. Lets start by implementing methods to provide basic functionality for interacting with the oracle to generate a verifiable random number. Then updating and reading a message stored persistently in the contract state to determine outcome of the game. Enter this command in your Terminal . Terminal cd src Defining Methods and Messages ​ Rename the file name from Protobuf/contract/hello_world_contract.proto to dice_master_contract.proto : Terminal mv Protobuf/contract/hello_world_contract.proto Protobuf/contract/dice_master_contract.proto open the project with your IDE. The implementation of file src/Protobuf/contract/dice_master_contract.proto is as follows: dice_master_contract.proto syntax = "proto3" ; import "aelf/core.proto" ; import "aelf/options.proto" ; import "google/protobuf/empty.proto" ; import "google/protobuf/wrappers.proto" ; import "Protobuf/reference/acs12.proto" ; import "Protobuf/message/request_interface.proto" ; // The namespace of this class option csharp_namespace = "AElf.Contracts.DiceMaster" ; service DiceMaster { // The name of the state class the smart contract is going to use to access blockchain state option ( aelf . csharp_state ) = "AElf.Contracts.DiceMaster.DiceMasterState" ; option ( aelf . base ) = "Protobuf/reference/acs12.proto" ; option ( aelf . base ) = "Protobuf/message/request_interface.proto" ; rpc Initialize ( google . protobuf . Empty ) returns ( google . protobuf . Empty ) { } rpc Play ( google . protobuf . Int64Value ) returns ( google . protobuf . Empty ) { } rpc Withdraw ( google . protobuf . Int64Value ) returns ( google . protobuf . Empty ) { } rpc Deposit ( google . protobuf . Int64Value ) returns ( google . protobuf . Empty ) { } rpc TransferOwnership ( aelf . Address ) returns ( google . protobuf . Empty ) { } rpc SetSubscriptionId ( google . protobuf . Int64Value ) returns ( google . protobuf . Empty ) { } rpc SetOracleNodeId ( google . protobuf . Int32Value ) returns ( google . protobuf . Empty ) { } rpc GetPlayAmountLimit ( google . protobuf . Empty ) returns ( PlayAmountLimitMessage ) { option ( aelf . is_view ) = true ; } rpc GetContractBalance ( google . protobuf . Empty ) returns ( google . protobuf . Int64Value ) { option ( aelf . is_view ) = true ; } rpc GetOwner ( google . protobuf . Empty ) returns ( google . protobuf . StringValue ) { option ( aelf . is_view ) = true ; } rpc GetSubscriptionId ( google . protobuf . Empty ) returns ( google . protobuf . Int64Value ) { option ( aelf . is_view ) = true ; } rpc GetOracleNodeId ( google . protobuf . Empty ) returns ( google . protobuf . Int32Value ) { option ( aelf . is_view ) = true ; } rpc GetPlayerInfo ( aelf . Address ) returns ( PlayerInfo ) { option ( aelf . is_view ) = true ; } } // An event that will be emitted from contract method call when Play is called. message PlayOutcomeEvent { option ( aelf . is_event ) = true ; int64 amount = 1 ; int64 won = 2 ; aelf . Address from = 3 ; } // An event that will be emitted from contract method call when Withdraw is called. message WithdrawEvent { option ( aelf . is_event ) = true ; int64 amount = 1 ; aelf . Address from = 2 ; aelf . Address to = 3 ; } // An event that will be emitted from contract method call when Deposit is called. message DepositEvent { option ( aelf . is_event ) = true ; int64 amount = 1 ; aelf . Address from = 2 ; aelf . Address to = 3 ; } // The message containing the play amount limits message PlayAmountLimitMessage { int64 minimumAmount = 1 ; int64 maximumAmount = 2 ; } message PlayedRecord { aelf . Address address = 1 ; int64 blockNumber = 2 ; } message PlayerInfo { aelf . Address address = 1 ; int64 dice1 = 2 ; int64 dice2 = 3 ; bool win = 4 ; int64 amount = 5 ; bool pending = 6 ; int64 blockNumber = 7 ; } Define Contract States ​ The implementation of file src/DiceMasterState.cs is as follows: src/DiceMasterState.cs using AElf . Sdk . CSharp . State ; using AElf . Types ; namespace AElf . Contracts . DiceMaster { // The state class is access the blockchain state public partial class DiceMasterState : ContractState { // A state to check if contract is initialized public BoolState Initialized { get ; set ; } // A state to store the owner address public SingletonState < Address > Owner { get ; set ; } public MappedState < Hash , PlayedRecord > PlayedRecords { get ; set ; } public SingletonState < int > OracleNodeId { get ; set ; } public SingletonState < long > SubscriptionId { get ; set ; } public MappedState < Address , PlayerInfo > PlayerInfos { get ; set ; } } } Token Contract Reference State ​ Create a new file token_contract.proto under src/Protobuf/reference/ . Replace this code of implementation file of token_contract.proto : token_contract.proto /** * MultiToken contract. */ syntax = "proto3" ; package token ; import "aelf/core.proto" ; import "aelf/options.proto" ; import "google/protobuf/empty.proto" ; import "google/protobuf/wrappers.proto" ; option csharp_namespace = "AElf.Contracts.MultiToken" ; service TokenContract { // Create a new token. rpc Create ( CreateInput ) returns ( google . protobuf . Empty ) { } // Issuing some amount of tokens to an address is the action of increasing that addresses balance // for the given token. The total amount of issued tokens must not exceed the total supply of the token // and only the issuer (creator) of the token can issue tokens. // Issuing tokens effectively increases the circulating supply. rpc Issue ( IssueInput ) returns ( google . protobuf . Empty ) { } // Transferring tokens simply is the action of transferring a given amount of tokens from one address to another. // The origin or source address is the signer of the transaction. // The balance of the sender must be higher than the amount that is transferred. rpc Transfer ( TransferInput ) returns ( google . protobuf . Empty ) { } // The TransferFrom action will transfer a specified amount of tokens from one address to another. // For this operation to succeed the from address needs to have approved (see allowances) enough tokens // to Sender of this transaction. If successful the amount will be removed from the allowance. rpc TransferFrom ( TransferFromInput ) returns ( google . protobuf . Empty ) { } // The approve action increases the allowance from the Sender to the Spender address, // enabling the Spender to call TransferFrom. rpc Approve ( ApproveInput ) returns ( google . protobuf . Empty ) { } rpc BatchApprove ( BatchApproveInput ) returns ( google . protobuf . Empty ) { } // This is the reverse operation for Approve, it will decrease the allowance. rpc UnApprove ( UnApproveInput ) returns ( google . protobuf . Empty ) { } // This method can be used to lock tokens. rpc Lock ( LockInput ) returns ( google . protobuf . Empty ) { } // This is the reverse operation of locking, it un-locks some previously locked tokens. rpc Unlock ( UnlockInput ) returns ( google . protobuf . Empty ) { } // This action will burn the specified amount of tokens, removing them from the token’s Supply. rpc Burn ( BurnInput ) returns ( google . protobuf . Empty ) { } // Set the primary token of side chain. rpc SetPrimaryTokenSymbol ( SetPrimaryTokenSymbolInput ) returns ( google . protobuf . Empty ) { } // This interface is used for cross-chain transfer. rpc CrossChainTransfer ( CrossChainTransferInput ) returns ( google . protobuf . Empty ) { } // This method is used to receive cross-chain transfers. rpc CrossChainReceiveToken ( CrossChainReceiveTokenInput ) returns ( google . protobuf . Empty ) { } // The side chain creates tokens. rpc CrossChainCreateToken ( CrossChainCreateTokenInput ) returns ( google . protobuf . Empty ) { } // When the side chain is started, the side chain is initialized with the parent chain information. rpc InitializeFromParentChain ( InitializeFromParentChainInput ) returns ( google . protobuf . Empty ) { } // Handle the transaction fees charged by ChargeTransactionFees. rpc ClaimTransactionFees ( TotalTransactionFeesMap ) returns ( google . protobuf . Empty ) { } // Used to collect transaction fees. rpc ChargeTransactionFees ( ChargeTransactionFeesInput ) returns ( ChargeTransactionFeesOutput ) { } rpc ChargeUserContractTransactionFees ( ChargeTransactionFeesInput ) returns ( ChargeTransactionFeesOutput ) { } // Check the token threshold. rpc CheckThreshold ( CheckThresholdInput ) returns ( google . protobuf . Empty ) { } // Initialize coefficients of every type of tokens supporting charging fee. rpc InitialCoefficients ( google . protobuf . Empty ) returns ( google . protobuf . Empty ) { } // Processing resource token received. rpc DonateResourceToken ( TotalResourceTokensMaps ) returns ( google . protobuf . Empty ) { } // A transaction resource fee is charged to implement the ACS8 standards. rpc ChargeResourceToken ( ChargeResourceTokenInput ) returns ( google . protobuf . Empty ) { } // Verify that the resource token are sufficient. rpc CheckResourceToken ( google . protobuf . Empty ) returns ( google . protobuf . Empty ) { } // Set the list of tokens to pay transaction fees. rpc SetSymbolsToPayTxSizeFee ( SymbolListToPayTxSizeFee ) returns ( google . protobuf . Empty ) { } // Update the coefficient of the transaction fee calculation formula. rpc UpdateCoefficientsForSender ( UpdateCoefficientsInput ) returns ( google . protobuf . Empty ) { } // Update the coefficient of the transaction fee calculation formula. rpc UpdateCoefficientsForContract ( UpdateCoefficientsInput ) returns ( google . protobuf . Empty ) { } // This method is used to initialize the governance organization for some functions, // including: the coefficient of the user transaction fee calculation formula, // the coefficient of the contract developer resource fee calculation formula, and the side chain rental fee. rpc InitializeAuthorizedController ( google . protobuf . Empty ) returns ( google . protobuf . Empty ) { } rpc AddAddressToCreateTokenWhiteList ( aelf . Address ) returns ( google . pr
프로젝트로 돌아가기