aelf 백서

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

OKEN" , symbol : "" , totalSupply : "" , } , } ) ; Here's what the function does: ​ Initializes a new form variable with default values needed to create a token. Fields include: tokenName , symbol and totalSupply . Now the form is ready for users to fill in the necessary details for their token related function interaction. Get CrossChain Contract ​ Let's write the helper function to Get CrossChain Contract to fetch the parent chain height later. Write the function to Get CrossChain Contract The create-token-modal/index.tsx file includes the code to create a fungible token. Find the comment // Step G - Get CrossChain Contract . Replace the existing getCrossChainContract function with this code snippet: create-token-modal/index.tsx // Step G - Get CrossChain Contract const getCrossChainContract = async ( aelf : any , wallet : any ) => { const crossChainContractName = "AElf.ContractNames.CrossChain" ; // get chain status const chainStatus = await aelf . chain . getChainStatus ( ) ; // get genesis contract address const GenesisContractAddress = chainStatus . GenesisContractAddress ; // get genesis contract instance const zeroContract = await aelf . chain . contractAt ( GenesisContractAddress , wallet ) ; // Get contract address by the read only method `GetContractAddressByName` of genesis contract const crossChainContractAddress = await zeroContract . GetContractAddressByName . call ( AElf . utils . sha256 ( crossChainContractName ) ) ; return await aelf . chain . contractAt ( crossChainContractAddress , wallet ) ; } ; What This Function Does: ​ Get chainStatus : It gets chainStatus from getChainStatus function which is there in aelf. Get GenesisContractAddress : It gets GenesisContractAddress from chainStatus. fetch zeroContract : It fetches zeroContract using GenesisContractAddress and wallet. fetch crossChainContractAddress : It fetch crossChainContractAddress by calling GetContractAddressByName method from zeroContract. Next, we'll write the Get the parent chain height function. Get the parent chain height ​ Write the function to get the parent chain height Scroll down to find the comment // Step H - Get the parent chain height . Replace the existing GetParentChainHeight function with the following code snippet: create-token-modal/index.tsx // Step H - Get the parent chain height // This function fetches the current height of the parent blockchain. const GetParentChainHeight = async ( ) => { try { const tdvwCrossChainContract = await getCrossChainContract ( tdvw , wallet ) ; // Call the smart contract method to get the parent chain height. const result = await tdvwCrossChainContract . GetParentChainHeight . call ( ) ; // Return the parent chain height if it exists, otherwise return an empty string. return result ? ( result . value as string ) : "" ; } catch ( error : any ) { // If there's an error, log it and return an error status. console . error ( error , "=====error in GetParentChainHeight" ) ; return "error" ; } } ; What This Function Does: ​ Calls Smart Contract Method : It interacts with the side chain smart contract method to fetch the current height of the parent blockchain. Returns Parent Chain's Height : It returns the parent chain's height if it exists. Next, we'll write the Fetch the Merkle path function. Fetch the Merkle path ​ Write the fetch the merkle path function Scroll down to find the comment // Step I - Fetch the merkle path by transaction Id . Replace the existing getMerklePathByTxId function with this code snippet: create-token-modal/index.tsx // Step I - Fetch the merkle path by transaction Id const getMerklePathByTxId = async ( aelf : any , txId : string ) => { try { const { MerklePathNodes } = await aelf . chain . getMerklePathByTxId ( txId ) ; const formattedMerklePathNodes = MerklePathNodes . map ( ( { Hash , IsLeftChildNode , } : { Hash : string ; IsLeftChildNode : boolean ; } ) => ( { hash : Hash , isLeftChildNode : IsLeftChildNode , } ) ) return { merklePathNodes : formattedMerklePathNodes } ; } catch ( error ) { console . error ( "Error fetching Merkle path:" , error ) ; throw new Error ( "Failed to get Merkle path by transaction ID." ) ; } } ; What This Function Does: ​ Fetches Merkle Path : It sends a request to fetch the merkle path using the transaction ID. Parses Response : It parses the response from the server as JSON. Returns Merkle Path Nodes : It extracts and returns the merkle path of the nodes from the JSON response. Get Token Contract ​ Write the Get Token Contract function Scroll down to find the comment // Step J - Get Token Contract . Replace the existing getTokenContract function with this code snippet: create-token-modal/index.tsx // Step J - Get Token Contract const getTokenContract = async ( aelf : any , wallet : any ) => { const tokenContractName = "AElf.ContractNames.Token" ; // get chain status const chainStatus = await aelf . chain . getChainStatus ( ) ; // get genesis contract address const GenesisContractAddress = chainStatus . GenesisContractAddress ; // get genesis contract instance const zeroContract = await aelf . chain . contractAt ( GenesisContractAddress , wallet ) ; // Get contract address by the read only method `GetContractAddressByName` of genesis contract const tokenContractAddress = await zeroContract . GetContractAddressByName . call ( AElf . utils . sha256 ( tokenContractName ) ) ; return await aelf . chain . contractAt ( tokenContractAddress , wallet ) ; } ; What This Function Does: ​ Get chainStatus : It gets chainStatus from getChainStatus function. Get GenesisContractAddress : It gets GenesisContractAddress from chainStatus. fetch zeroContract : It fetches zeroContract using GenesisContractAddress and wallet. fetch tokenContractAddress : It fetches tokenContractAddress by calling GetContractAddressByName method from zeroContract. Create Fungible Token on the MainChain ​ Write a function to Create a new Fungible Token on the MainChain Scroll down to find the comment // Step K - Create Token on MainChain . Replace the existing createTokenOnMainChain function with this code snippet: create-token-modal/index.tsx // Step K - Create Token on MainChain const createTokenOnMainChain = async ( values : { tokenName : string ; symbol : string ; totalSupply : string ; } ) => { setFormLoading ( true ) ; let createMainChainTokenLoadingId ; try { createMainChainTokenLoadingId = toast . loading ( "Creating $TOKEN on MainChain..." ) ; // Preparing Parameter for Create Function const createTokenMainChainInput = { tokenName : values . tokenName , symbol : values . symbol , totalSupply : Number ( values . totalSupply ) + Number ( extraRewardAmount ) , issuer : currentWalletAddress , isBurnable : true , issueChainId : sidechain_from_chain_id , owner : currentWalletAddress , externalInfo : { } , } ; const resultMainchain = await mainChainSmartContract ?. callSendMethod ( "Create" , currentWalletAddress as string , createTokenMainChainInput ) ; console . log ( "========= result of create New $TOKEN =========" , resultMainchain ) ; toast . update ( createMainChainTokenLoadingId , { render : "$TOKEN Created Successfully on MainChain" , type : "success" , isLoading : false , } ) ; return "success" ; } catch ( error : any ) { if ( ! createMainChainTokenLoadingId ) { return "error" ; } handleCloseModal ( ) ; toast . update ( createMainChainTokenLoadingId , { render : error . message , type : "error" , isLoading : false , } ) ; return "error" ; } finally { removeNotification ( createMainChainTokenLoadingId as Id , 5000 ) ; } } ; tip ℹ️ Note: You need to get symbol from the Portkey wallet. Follow Steps to get TOKEN symbol from Portkey Wallet: Open Portkey Wallet. Go to the NFTs tab. You will find the SEED that you already got from the above seed generation step. Click on the SEED to see details. You will find the Token Symbol inside the Token Creation via This Seed section. Copy and use that value of the token symbol. What this function does: ​ Prepares Parameters : Constructs input parameters for creating the token, including token details and the issuer's information. Calls Smart Contract : Sends a request to the mainchain smart contract to create the token using the prepared parameters. Return Status : Returns "success" if the token is created successfully; otherwise, returns "error" . Write the Function to Validate Token Info Now, let's write the Validate TOKEN Info function. Scroll down to find the comment // Step L - Validate Mainchain Token Create's Transaction . Replace the existing validateToken function with this code snippet: create-token-modal/index.tsx // Step L - Validate Mainchain Token Create's Transaction const validateToken = async ( values : ITokenParams ) => { let validateTOKENLoadingId ; try { setFormLoading ( true ) ; // Start Loading before initiate the transaction validateTOKENLoadingId = toast . loading ( < CustomToast title = "Transaction is getting validated on aelf blockchain. Please wait!" message = "Validation means transaction runs through a consensus algorithm to be selected or rejected. Once the status changes process will complete. It usually takes some time in distributed systems." / > ) ; // Create an object with the necessary information for token validation. const validateInput = { symbol : values . symbol , tokenName : values . tokenName , totalSupply : Number ( values . totalSupply ) + Number ( extraRewardAmount ) , issuer : currentWalletAddress , isBurnable : true , issueChainId : sidechain_from_chain_id , owner : currentWalletAddress , externalInfo : { } , } ; // get mainnet contract const aelfTokenContract = await getTokenContract ( aelf , wallet ) ; // prepare Sign the transaction using contract method (ValidateTokenInfoExists Function) const signedTx = aelfTokenContract . ValidateTokenInfoExists . getSignedTx ( validateInput ) ; // send the transaction using signed Transaction const { TransactionId : VALIDATE_TXID } = await aelf . chain . sendTransaction ( signedTx ) ; await delay ( 3000 ) ; // get Validate Result let VALIDATE_TXRESULT = await aelf . chain . getTxResult ( VALIDATE_TXID ) ; await delay ( 3000 ) ; // if dAppChain index has a MainChain height greater than validateTokenInfoExist's let heightDone = false ; while ( ! heightDone ) { // get latest index Hight const sideIndexMainHeight = await GetParentChainHeight ( ) ; if ( // check the latest index Hight is grater than or equal Number ( sideIndexMainHeight ) >= Number ( VALIDATE_TXRESULT . Transaction . RefBlockNumber ) ) { VALIDATE_TXRESULT = await aelf . chain . getTxResult ( VALIDATE_TXID ) ; heightDone = true ; } } console . log ( VALIDATE_TXRESULT , "VALIDATE_TXRESULT=====2" ) ; const merklePath = await getMerklePathByTxId ( aelf , VALIDATE_TXID ) ; toast . update ( validateTOKENLoadingId , { render : "Validating $TOKEN Successfully Executed" , type : "success" , isLoading : false , } ) ; // return necessary values return { parentChainHeight : VALIDATE_TXRESULT . BlockNumber , signedTx : signedTx , merklePath : merklePath , } ; } catch ( error : any ) { toast . update ( validateTOKENLoadingId as Id , { render : error . message , type : "error" , isLoading : false , } ) ; handleCloseModal ( ) ; return "error" ; } finally { removeNotification ( validateTOKENLoadingId as Id ) ; } } ; Here's what the function does: ​ Prepares Validation Input: Constructs the input parameters needed for validating the token. Gets Token Contract: Retrieves the token contract instance from the MainChain. Signs and Sends Transaction: Signs the transaction to validate the token info and sends it to the blockchain. Polls for Transaction Result: Waits for the transaction result and ensures that the transaction has reached the required block height. Fetches Merkle Path: Retrieves the Merkle path for the validated transaction. Create Fungible Token on dAppChain ​ Write a Function to Create Token on the dAppChain Scroll down to find the comment // Step M - Create a Token on the dAppChain. . Replace the existing createTokenOnSideChain function with this code snippet: create-token-modal/index.tsx // Step M - Create a Token on the dAppChain. const createTokenOnSideChain = async ( values : ITokenValidateResult ) => { let createSideChainTokenLoadingId ; try { createSideChainTokenLoadingId = toast . loading ( "Creating $TOKEN on SideChain..." ) ; // Prepare create Token Parameters const CREATE_TOKEN_PARAMS = { fromChainId : mainchain_from_chain_id , parentChainHeight : values . parentChainHeight , transactionBytes : Buffer . from ( values . signedTx , "hex" ) . toString ( "base64" ) , merklePath : values . merklePath , } ; // Calling CrossChainCreateToken function on dAppChain await sideChainSmartContract ?. callSendMethod ( "CrossChainCreateToken" , currentWalletAddress as string , CREATE_TOKEN_PARAMS ) ; toast . update ( createSideChainTokenLoadingId , { render : "$TOKEN Created Successfully On SideChain" , type : "success" , isLoading : false , } ) ; return "success" ; } catch ( error ) { toast . update ( createSideChainTokenLoadingId as Id , { render : "$TOKEN Created Successfully On SideChain" , type : "success" , isLoading : false , } ) ; console . log ( "error====" , error ) ; return "error" ; } finally { removeNotification ( createSideChainTokenLoadingId as Id ) ; } } ; Here's what the function does: ​ Prepares Parameters: Constructs the parameters needed for creating the token on the dAppChain, including chain IDs & block height, transaction data, and Merkle path. Calls Smart Contract Method: Sends the transaction to the dAppChain smart contract to create the token. Issue the created token on the dAppChain ​ Write a Function to Issue Token which has been Created on the dAppChain. Scroll down to find the comment // Step N - Issue Token on dAppChain . Replace the existing issueTokenOnSideChain function with this code snippet: create-token-modal/index.tsx // Step N - Issue Token on dAppChain const issueTokenOnSideChain = async ( values : { symbol : string ; amount : string | number ; memo : string ; } ) => { let issueTokenLoadingId ; try { setFormLoading ( true ) ; issueTokenLoadingId = toast . loading ( "Issuing $TOKEN on SideChain..." ) ; // prepate parameters const issueTokenInput = { symbol : values . symbol , amount : values . amount , memo : values . memo , to : currentWalletAddress , } ; // call Issue function on dAppChain smart contract const result = await sideChainSmartContract ?. callSendMethod ( "Issue" , currentWalletAddress as string , issueTokenInput ) ; console . log ( "========= result of issue Token Transaction =========" , result ) ; toast . update ( issueTokenLoadingId , { render : "$TOKEN Issue Successfully Executed" , type : "success" , isLoading : false , } ) ; toast . success ( "You will get $TOKEN on your Wallet! It can take sometimes to get into your wallet" ) ; return result ; } catch ( error : any ) { handleCloseModal ( ) ; toast . update ( issueTokenLoadingId as Id , { render : error . message , type : "error" , isLoading : false , } ) ; return "error" ; } finally { removeNotification ( issueTokenLoadingId as Id ) ; } } ; Here's what the function does: ​ Prepares Issuance Input: Constructs the input parameters for issuing the token including symbol, amount, memo, and recipient address. Calls Smart Contract Method: Sends the transaction to the dAppChain smart contract to issue the token. Handles Success: Updates the notification to show successful issuance and notifies the user that the token will appear in their wallet. Transfer Token to Staking Contract ​ Create a Function to Transfer Token to the Staking Contract for Reward Balance Scroll down to find the comment // Step O - Transfer TOKEN to Staking Contract . Replace the existing transferTokenToStakingContract function with this code snippet: create-token-modal/index.tsx // Step O - Transfer TOKEN to Staking Contract const transferTokenToStakingContract = async ( amount : string , symbol : string ) => { let transferTokenLoadingId = toast . loading ( "Transferring $TOKEN to Staking Contract for Reward Balance" ) ; // prepare parameters try { const transferNtfInput = { to : stakingContractAddress , symbol : symbol , amount : amount , memo : "Transfering Amount to Staking Contract for Reward Balance" , } ; // call Transfer function on dAppChain contract await sideChainSmartContract ?. callSendMethod ( "Transfer" , currentWalletAddress as string , transferNtfInput ) ; toast . update ( transferTokenLoadingId , { render : "$TOKEN Transfer Successfully!" , type : "success" , isLoading : false , } ) ; return "success" ; } catch ( error : any ) { toast . update ( transferTokenLoadingId , { render : error . message , type : "error" , isLoading : false , } ) ; return "error" ; } finally { removeNotification ( transferTokenLoadingId as Id ) ; } } ; Here's what the function does: ​ Prepares Transfer Input: Constructs the input parameters to transfer the token including to address, symbol, amount & memo. Calls Smart Contract Method: Sends the transaction to the dAppChain smart contract to transfer the token. Initialize the staking contract ​ Create a Function to Initialize the Staking Contract using Token Address Scroll down to find the comment // Step P - Initializing the staking contract . Replace the existing initializedContract function with this code snippet: create-token-modal/index.tsx // Step P - Initializing the staking contract const initializedContract = async ( tokenContractAddress : string ) => { let initializeLoadingId : any ; try { initializeLoadingId = toast . loading ( "Staking Contract is Initialising..." ) ; // call Initialize function on Staking contract using token contract const result = await stakingContract ?. callSendMethod ( "Initialize" , currentWalletAddress as string , { tokenContractAddress } ) ; toast . update ( initializeLoadingId , { render : "Staking Contract Initialised Successful" , type : "success" , isLoading : false , } ) ; return "true" ; } catch ( error : any ) { toast . update ( initializeLoadingId , { render : error . message , type : "error" , isLoading : false , } ) ; return "error" ; } finally { removeNotification ( initializeLoadingId as Id ) ; } } ; Here's what the function does: ​ Calls Smart Contract Method: Sends the transaction to the staking smart contract to initialize the contract using the token address. Configure Submit Form ​ Create a Function to Handle Submit of Create form Now, let's write the create token function. Scroll down to find the comment // Step Q - handle Submit of Create Token . Replace the existing onSubmit function with this code snippet: create-token-modal/index.tsx // Step Q - handle Submit of Create Token const onSubmit = async ( values : { tokenName : string ; symbol : string ; totalSupply : string ; } ) => { try { // creating TOKEN on mainchain const mainChainResult = await createTokenOnMainChain ( values ) ; if ( mainChainResult === "error" ) { setFormLoading ( false ) ; return ; } await delay ( 3000 ) ; // Validating Transaction of Create Token on mainchain const
프로젝트로 돌아가기