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