aelf 백서

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

validateTokenData : ITokenValidateResult | "error" = await validateToken ( values ) ; if ( validateTokenData === "error" ) { setFormLoading ( false ) ; return ; } // creating TOKEN on side chain once Transaction validate const sideChainResult = await createTokenOnSideChain ( validateTokenData ) ; if ( sideChainResult === "error" ) { setFormLoading ( false ) ; return ; } // Issuing TOKEN on side chain once it's created succefully const issueTokenResult : any = await issueTokenOnSideChain ( { symbol : values . symbol , amount : Number ( values . totalSupply ) + Number ( extraRewardAmount ) , memo : "We are issuing Token" , } ) ; if ( issueTokenResult === "error" ) { setFormLoading ( false ) ; return ; } // get TokenContractDetails from transactio logs on issues Token const tokenLog = issueTokenResult . data . Logs . find ( ( { Name } : { Name : string } ) => Name === "Issued" ) if ( ! tokenLog ) { toast . error ( "Error in Token Address" ) ; return } // Transferring Reward Amount on Staking Contract await transferTokenToStakingContract ( extraRewardAmount , values . symbol ) ; // Initializing Staking smart contract using Token Address await initializedContract ( tokenLog . Address ) ; } catch ( error : any ) { toast . error ( error ) ; } finally { setFormLoading ( false ) ; handleCloseModal ( ) ; } } ; Here's what the function does: ​ Creates Token on the MainChain: Calls createTokenOnMainChain to create the token on the mainchain. If it fails, it updates the transaction status and exits. Validates Create Token Transaction: Waits for 3 seconds, then calls validateToken to validate the token. If validation fails, it updates the transaction status and exits. Creates Token on the dAppChain: Calls createTokenOnSideChain to create the token on the dAppChain using the validated data. If it fails, it updates the transaction status and exits. Issues Token on the dAppChain: Calls issueTokenOnSideChain to issue the token. Updates the transaction status to false after completion. Transferring Reward Amount to the Staking Contract : Calls transferTokenToStakingContract to transfer the reward amount to the staking contract. Initializing Staking smart contract: Calls initializedContract to initialize the staking smart contract using the token address. Fetch Token Data ​ Let's write the function to fetch the token data from user's wallet using graphql API. Step 1: Locate the File go to the /src/pages/home/index.tsx file. Step 2: Write Function to fetch the fungible token data Find the comment // Step R - fetch Fungible Token data . Replace the existing fetchTokenData function with this code snippet: home/index.tsx // Step R - fetch Fungible Token data const fetchTokenData = async ( ) => { if ( ! currentWalletAddress ) { return ; } try { // Your GraphQL query and variables from the curl command const query = ` query ExampleQuery($dto: GetCAHolderTokenBalanceDto) { caHolderTokenBalanceInfo(dto: $dto) { data { balance tokenInfo { symbol } } } } ` ; const variables = { dto : { chainId : "tDVW" , // AELF or tDVW skipCount : 0 , maxResultCount : 100 , caAddressInfos : [ { caAddress : currentWalletAddress , } , ] , } , } ; // Axios POST request to the GraphQL endpoint const response = await axios . post ( "https://dapp-aa-portkey-test.portkey.finance/Portkey_V2_DID/PortKeyIndexerCASchema/graphql" , { query : query , variables : variables , } , { headers : { "content-type" : "application/json" , } , } ) ; // Handle the response const tokensData = response . data . data . caHolderTokenBalanceInfo . data ; // find token detilas from API data if ( tokensData && tokensData . length > 0 ) { const filterTokenInfo = tokensData . find ( ( data : ITokenInfo ) => data . tokenInfo . symbol . length === 10 , [ ] ) ; if ( filterTokenInfo ) { setTokenInfo ( filterTokenInfo ) ; } } } catch ( err ) { console . log ( "error" , err ) ; } } ; Here's what the function does: ​ Fetch Token balance: Fetches token balance using graphql api. Filter Token Details: It finds the token details from the API response. Now, it's time to start the implementation of the staking functionality. Deposit Stake Amount on the Staking Contract ​ As we have completed Create Token and Fetch Token balance functionality, it's time to acheive Stake Token functionality using the staking smart contract. Now, let's prepare the Deposit Stake Amount related functions. Transfer Tokens to the Staking Contract ​ First, we need to transfer stake amount to the staking contract address using dAppChain contract and then we can call the GetDeposits function on the staking contract. Scroll down to find the comment // Step S - Function to transfer tokens to the staking contract . Replace the existing transferTokenToStakingContract function with this code snippet: home/index.tsx // Step S - Function to transfer tokens to the staking contract const transferTokenToStakingContract = async ( amount : string ) => { // Show a loading toast notification while the transfer is in progress let transferTokenLoadingId = toast . loading ( "$TOKEN Deposit Transaction Executing" ) ; try { // Prepare the transfer input with required parameters const transferNtfInput = { to : stakingContractAddress , // Address of the staking contract symbol : tokenInfo ?. tokenInfo . symbol , // Symbol of the token being transferred amount : amount , // Amount to be transferred memo : "Transferring Amount to Staking Contract for Deposit Token" , // Description or memo for the transaction } ; // Call the transfer method on the side chain smart contract await sideChainSmartContract ?. callSendMethod ( "Transfer" , currentWalletAddress as string , // Address of the current wallet initiating the transfer transferNtfInput ) ; // Update the toast notification on successful transfer toast . update ( transferTokenLoadingId , { render : "$TOKEN Deposit Successfully!" , type : "success" , isLoading : false , } ) ; removeNotification ( transferTokenLoadingId ) ; // Remove the notification return "success" ; // Return success status } catch ( error : any ) { // Handle any error during the token transfer and update the toast notification toast . update ( transferTokenLoadingId , { render : error . message , // Display the error message type : "error" , isLoading : false , } ) ; removeNotification ( transferTokenLoadingId ) ; // Remove the notification return "error" ; // Return error status } } ; Create Handle Staking function ​ Now, let's create the function to handle staking, as we have already completed transferTokenToStakingContract function. Scroll down to find the comment // Step T - Function to handle staking of the tokens . Replace the existing handleStaking function with this code snippet: home/index.tsx // Step T - Function to handle staking of the tokens const handleStaking = async ( ) => { // Validate the amount and handle any errors const isError = handleAmountError ( amount ) ; if ( isError ) { return ; // Exit if there is an error with the amount } let stakingLoadingId : any ; // Variable to store the loading toast ID try { // Transfer the token to the staking contract before proceeding with staking const result : "success" | "error" = await transferTokenToStakingContract ( amount ) ; // Exit if the transfer encountered an error if ( result === "error" ) { return ; } // Show a loading toast notification for the staking process stakingLoadingId = toast . loading ( "Staking $TOKEN on Smart Contract..." ) ; // Prepare the deposit parameters const DEPOSIT_PARAMS = { tokenSymbol : tokenInfo ?. tokenInfo . symbol , // Symbol of the token being staked amount : amount , // Amount being staked lockTime : 300 , // Time for which the tokens are locked } ; // Call the deposit method on the staking contract await stakingContract ?. callSendMethod ( "Deposit" , currentWalletAddress as string , // Address of the current wallet DEPOSIT_PARAMS ) ; // Fetch the updated deposit data and total staked amount after staking fetchDepositData ( ) ; fetchTotalStakedAmount ( ) ; // Reset the edited status and clear the amount field setIsEdited ( false ) ; setAmount ( "" ) ; // Update the toast notification for successful staking toast . update ( stakingLoadingId , { render : "$TOKEN Staked Successfully" , type : "success" , isLoading : false , } ) ; removeNotification ( stakingLoadingId ) ; // Remove the notification } catch ( error : any ) { // Handle any error during staking and update the toast notification setAmount ( "" ) ; // Clear the amount field in case of an error toast . update ( stakingLoadingId , { render : error . message , // Display the error message type : "error" , isLoading : false , } ) ; removeNotification ( stakingLoadingId ) ; // Remove the notification return "error" ; // Return error status } } ; Fetch Deposited (Staked) Tokens ​ Find the comment // Step U - Function to fetch deposited (staked) tokens for the connected wallet address . Replace the existing fetchDepositData function with this code snippet: home/index.tsx // Step U - Function to fetch deposit data for the current wallet address const fetchDepositData = async ( ) => { try { // Call the "GetDeposits" method on the staking contract to get deposits for the wallet address const deposite : any = await stakingContract ?. callViewMethod ( "GetDeposits" , { value : currentWalletAddress as string } ) ; // Check if there are any deposits in the returned data if ( deposite . data && deposite . data . deposits . length > 0 ) { setDepositData ( deposite . data . deposits ) ; // Update state with the deposit data } else { setDepositData ( [ ] ) ; // If no deposits, set the data to an empty array } } catch ( error ) { // Log and handle any errors during the fetch console . log ( "error" , error ) ; return "error" ; } } ; Fetch Total Staked Amount ​ Find the comment // Step V - Function to fetch the total staked amount from the staking contract . Replace the existing fetchTotalStakedAmount function with this code snippet: home/index.tsx // Step V - Function to fetch the total staked amount from the staking contract const fetchTotalStakedAmount = async ( ) => { try { // Call the "GetTotalStakedAmount" method to get the total staked amount const amount : any = await stakingContract ?. callViewMethod ( "GetTotalStakedAmount" , "" ) ; // Check if there is valid data for the total staked amount if ( amount ?. data ) { setTotalStakedAmount ( amount . data . value ) ; // Update state with the total staked amount } else { setTotalStakedAmount ( "0" ) ; // If no data, set the total staked amount to "0" } } catch ( error ) { // Log and handle any errors during the fetch console . log ( "error" , error ) ; return "error" ; } } ; Withdraw Staked Tokens ​ Users can withdraw the staked amount after the staking period is over for a specific deposit. Find the comment // Step W - Function to withdraw staked tokens based on a deposit ID . Replace the existing withdrawStake function with this code snippet: home/index.tsx // Step W - Function to withdraw staked tokens based on a deposit ID const withdrawStake = async ( depositId : string ) => { let withdrawLoadingId : any ; // Variable to store the loading toast ID setIsWithdrawing ( true ) ; // Set the withdrawing state to true try { // Show a loading toast notification while the withdrawal is in progress withdrawLoadingId = toast . loading ( "$TOKEN Withdrawal in Progress..." ) ; // Call the "Withdraw" method on the staking contract to withdraw based on deposit ID await stakingContract ?. callSendMethod ( "Withdraw" , currentWalletAddress as string , // Pass the current wallet address { depositId } // Pass the deposit ID to withdraw ) ; // Update the toast notification on successful withdrawal toast . update ( withdrawLoadingId , { render : "$TOKEN Withdraw Successful" , type : "success" , isLoading : false , } ) ; removeNotification ( withdrawLoadingId ) ; // Remove the loading notification } catch ( error : any ) { // Handle any errors during withdrawal and update the toast notification toast . update ( withdrawLoadingId , { render : error . message , // Display the error message type : "error" , isLoading : false , } ) ; removeNotification ( withdrawLoadingId ) ; // Remove the loading notification return "error" ; // Return error status } finally { // After withdrawal, fetch updated deposit data and total staked amount fetchDepositData ( ) ; fetchTotalStakedAmount ( ) ; setIsWithdrawing ( false ) ; // Set the withdrawing state to false } } ; Emergency Withdraw Staked Tokens ​ Users can withdraw their staked amount at any time through the emergency withdrawal function before the staking period gets over. Find the comment // Step X - Function to perform an emergency withdrawal of staked tokens based on a deposit ID . Replace the existing emergencyWithdrawStake function with this code snippet: home/index.tsx // Step X - Function to perform an emergency withdrawal of staked tokens based on a deposit ID const emergencyWithdrawStake = async ( depositId : string ) => { let withdrawLoadingId : any ; // Variable to store the loading toast ID setIsWithdrawing ( true ) ; // Set the withdrawing state to true try { // Show a loading toast notification while the emergency withdrawal is in progress withdrawLoadingId = toast . loading ( "Emergency $TOKEN Withdrawal in Progress..." ) ; // Call the "ForceWithdraw" method on the staking contract to forcefully withdraw the deposit await stakingContract ?. callSendMethod ( "ForceWithdraw" , currentWalletAddress as string , // Pass the current wallet address { value : depositId } // Pass the deposit ID for the emergency withdrawal ) ; // Update the toast notification on successful emergency withdrawal toast . update ( withdrawLoadingId , { render : "$TOKEN Withdraw Successful" , type : "success" , isLoading : false , } ) ; removeNotification ( withdrawLoadingId ) ; // Remove the loading notification } catch ( error : any ) { // Handle any errors during emergency withdrawal and update the toast notification toast . update ( withdrawLoadingId , { render : error . message , // Display the error message type : "error" , isLoading : false , } ) ; removeNotification ( withdrawLoadingId ) ; // Remove the loading notification return "error" ; // Return error status } finally { // After the emergency withdrawal, fetch updated deposit data fetchDepositData ( ) ; setIsWithdrawing ( false ) ; // Set the withdrawing state to false } } ; Set Staking Contract Address ​ You need to set your deployed Staking contract Address in utils file so let's set it now. Step 1: Locate the File Go to the /src/lib/utils.tsx file. Step 2: Set Deployed Staking Contract Address Find the comment // Step Y - Staking contract address on below of page. Replace your deployed staking contract with value of stakingContractAddress ( your_deployed_stakinng_contract ). src/lib/utils.tsx // Step Y - Staking contract address export const stakingContractAddress = "your_deployed_staking_contract_address" As we've written all the necessary frontend functions and components, we're ready to run the Staking dApp application in the next step. Run Application ​ In this step, we will run the Staking 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 staking/2-dapp folder. You should observe the following as shown below. Upon clicking on the localhost URL , you should be directed to the Staking 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 codespace will automatically forward port, 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 Staking 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 delegates 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 aelf Testnet network by selecting it: danger Please make sure you are using aelf Testnet in order to be able to receive your testnet tokens from the Faucet. Proceed to sign up with a Google Account or your preferred login method and complete the necessary accounts creation prompts and you should observe the following interface once you have signed up. With that, you have successfully created your very first Portkey wallet within seconds. How easy was that? info It is highly recommended to pin the Portkey wallet extension for easier access and navigation to your Portkey wallet! Next, click on ‘Open Portkey’ and you should now observe the following as shown below. Connect Portkey Wallet Click on "Connect Wallet" to connect your Portkey wallet. You will get a connection request on Portkey wallet as you can see in the below image. Click on Approve button. The button will change to "Your Wallet Address" when the connection is successful. Create Fungible Token Click on "Create Token" button to create new Fungible Token. The Create Token Popup modal will appear with prefilled token name. (You can modify the token name) Now, you need Token Seed to create the new token. If you don't have Token Seed then please follow this steps to get it. Open your Portkey Wallet and you will find the TOKEN Symbol on the NFT Tab. Copy the Token Symbol and use it inside the Symbol field of the token creation form. Fill other necessary details like Total Supply . Click on the Cre
프로젝트로 돌아가기