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
프로젝트로 돌아가기